From 14555a25d02120b05ac3ebb040e29ea80eaa0b17 Mon Sep 17 00:00:00 2001 From: Boris Date: Sat, 20 Jul 2024 16:49:00 +0200 Subject: [PATCH] feat: pipelines and tasks (#119) * feat: simple graph pipeline * feat: implement incremental graph generation * fix: various bug fixes * fix: upgrade weaviate-client --------- Co-authored-by: Vasilije <8619304+Vasilije1990@users.noreply.github.com> --- .github/workflows/test_common.yml | 10 +- .../modules/ingestion/DataView/DataView.tsx | 4 - .../src/modules/ingestion/addData.ts | 5 +- .../src/ui/Partials/SearchView/SearchView.tsx | 4 +- cognee/__init__.py | 2 +- cognee/api/client.py | 52 +- cognee/api/v1/add/add.py | 1 - cognee/api/v1/cognify/cognify.py | 28 +- cognee/api/v1/cognify/cognify_v2.py | 139 + cognee/api/v1/config/config.py | 3 + cognee/api/v1/prune/prune.py | 12 +- cognee/api/v1/search/search.py | 24 +- cognee/base_config.py | 2 +- .../data/chunking/create_chunking_engine.py | 14 +- .../data/chunking/get_chunking_engine.py | 2 +- .../databases/graph/__init__.py | 1 + .../infrastructure/databases/graph/config.py | 2 +- .../databases/graph/falkordb/adapter.py | 25 +- ...et_graph_client.py => get_graph_engine.py} | 7 +- .../databases/graph/graph_db_interface.py | 12 + .../databases/graph/neo4j_driver/adapter.py | 248 +- .../databases/graph/networkx/adapter.py | 82 +- .../relational/duckdb/DuckDBAdapter.py | 15 +- .../vector/falkordb/FalkorDBAdapter.py | 7 +- .../vector/lancedb/LanceDBAdapter.py | 27 +- .../databases/vector/qdrant/QDrantAdapter.py | 13 +- .../databases/vector/vector_db_interface.py | 14 +- .../vector/weaviate_db/WeaviateAdapter.py | 44 +- .../files/storage/LocalStorage.py | 10 +- .../files/storage/StorageManager.py | 3 +- .../files/utils/get_file_metadata.py | 15 - .../infrastructure/llm/anthropic/adapter.py | 3 +- cognee/infrastructure/llm/config.py | 4 + cognee/infrastructure/llm/get_llm_client.py | 2 +- cognee/infrastructure/llm/openai/adapter.py | 70 +- .../llm/prompts/categorize_summary.txt | 4 +- .../llm/prompts/generate_graph_prompt.txt | 62 +- .../llm/prompts/summarize_content.txt | 4 +- cognee/modules/classification/__init__.py | 0 .../classification/classify_text_chunks.py | 152 + .../cognify/graph/add_node_connections.py | 4 +- .../cognify/graph/save_chunk_relationships.py | 0 .../cognify/graph/save_document_node.py | 18 + cognee/modules/cognify/vector/__init__.py | 1 + .../cognify/vector/save_data_chunks.py | 97 + cognee/modules/data/chunking/__init__.py | 3 + .../__tests__/chunk_by_paragraph.test.py | 53 + .../data/chunking/chunk_by_paragraph.py | 69 + .../data/chunking/chunk_by_sentence.py | 28 + cognee/modules/data/chunking/chunk_by_word.py | 60 + cognee/modules/data/deletion/__init__.py | 1 + cognee/modules/data/deletion/prune_data.py | 7 + cognee/modules/data/deletion/prune_system.py | 16 +- cognee/modules/data/extraction/__init__.py | 1 + .../data/extraction/data_summary/__init__.py | 0 .../data_summary/models/TextSummary.py | 5 + .../data_summary/summarize_text_chunks.py | 36 + .../data/extraction/extract_categories.py | 14 +- .../data/extraction/extract_summary.py | 2 +- .../modules/data/extraction/extract_topics.py | 113 + .../data/extraction/extract_topics_naive.py | 66 + .../add_model_class_to_graph.py | 70 + .../establish_graph_topology.py | 20 + .../knowledge_graph/expand_knowledge_graph.py | 117 + .../knowledge_graph/extract_content_graph.py | 8 +- cognee/modules/data/extraction/texts.json | 7 + cognee/modules/data/processing/__init__.py | 0 .../processing/chunk_types/DocumentChunk.py | 10 + .../document_types/AudioDocument.py | 122 + .../processing/document_types/Document.py | 8 + .../document_types/ImageDocument.py | 124 + .../processing/document_types/PdfDocument.py | 109 + .../processing/document_types/TextDocument.py | 112 + .../processing/document_types/__init__.py | 2 + .../__tests__/PdfDocument.test.py | 13 + .../__tests__/artificial-inteligence.pdf | Bin 0 -> 29616 bytes .../__tests__/soldiers-home.pdf | Bin 0 -> 33733 bytes .../data/processing/filter_affected_chunks.py | 25 + .../modules/data/processing/has_new_chunks.py | 30 + .../data/processing/process_documents.py | 41 + .../data/processing/remove_obsolete_chunks.py | 29 + cognee/modules/ingestion/classify.py | 2 +- .../ingestion/data_types/BinaryData.py | 2 +- .../modules/ingestion/data_types/TextData.py | 4 +- cognee/modules/ingestion/save_data_to_file.py | 4 +- cognee/modules/pipelines/Pipeline.py | 18 + cognee/modules/pipelines/__init__.py | 2 + cognee/modules/pipelines/models/Pipeline.py | 22 + .../modules/pipelines/models/PipelineTask.py | 14 + cognee/modules/pipelines/models/Task.py | 24 + .../modules/pipelines/operations/__init__.py | 0 .../operations/__tests__/__index__.py | 0 .../__tests__/artificial-inteligence.v1.pdf | Bin 0 -> 29616 bytes .../__tests__/artificial-inteligence.v2.pdf | Bin 0 -> 55375 bytes .../operations/__tests__/get_graph_url.py | 14 + .../operations/__tests__/run_tasks.test.py | 34 + .../modules/pipelines/operations/add_task.py | 4 + .../pipelines/operations/run_parallel.py | 12 + .../modules/pipelines/operations/run_tasks.py | 90 + cognee/modules/pipelines/tasks/Task.py | 32 + .../modules/search/graph/search_adjacent.py | 45 +- .../modules/search/graph/search_categories.py | 65 - .../modules/search/graph/search_neighbour.py | 74 - .../modules/search/graph/search_similarity.py | 22 + cognee/modules/search/graph/search_summary.py | 53 +- .../extraction/categorize_relevant_summary.py | 10 +- .../search/vector/search_similarity.py | 59 - .../modules/search/vector/search_traverse.py | 21 + cognee/modules/topology/topology.py | 81 +- cognee/shared/data_models.py | 27 +- cognee/shared/utils.py | 13 + .../test_data/artificial-intelligence.pdf | Bin 0 -> 29616 bytes cognee/tests/test_library.py | 105 +- cognee/tests/test_neo4j.py | 77 +- cognee/tests/test_qdrant.py | 72 +- cognee/tests/test_weaviate.py | 61 +- docker-compose-vanilla.yml | 41 - docker-compose.yml | 2 +- notebooks/full_run.ipynb | 8 +- poetry.lock | 2485 ++++++++++------- pyproject.toml | 20 +- 121 files changed, 4409 insertions(+), 1779 deletions(-) create mode 100644 cognee/api/v1/cognify/cognify_v2.py rename cognee/infrastructure/databases/graph/{get_graph_client.py => get_graph_engine.py} (87%) create mode 100644 cognee/modules/classification/__init__.py create mode 100644 cognee/modules/classification/classify_text_chunks.py create mode 100644 cognee/modules/cognify/graph/save_chunk_relationships.py create mode 100644 cognee/modules/cognify/graph/save_document_node.py create mode 100644 cognee/modules/cognify/vector/__init__.py create mode 100644 cognee/modules/cognify/vector/save_data_chunks.py create mode 100644 cognee/modules/data/chunking/__init__.py create mode 100644 cognee/modules/data/chunking/__tests__/chunk_by_paragraph.test.py create mode 100644 cognee/modules/data/chunking/chunk_by_paragraph.py create mode 100644 cognee/modules/data/chunking/chunk_by_sentence.py create mode 100644 cognee/modules/data/chunking/chunk_by_word.py create mode 100644 cognee/modules/data/deletion/prune_data.py create mode 100644 cognee/modules/data/extraction/data_summary/__init__.py create mode 100644 cognee/modules/data/extraction/data_summary/models/TextSummary.py create mode 100644 cognee/modules/data/extraction/data_summary/summarize_text_chunks.py create mode 100644 cognee/modules/data/extraction/extract_topics.py create mode 100644 cognee/modules/data/extraction/extract_topics_naive.py create mode 100644 cognee/modules/data/extraction/knowledge_graph/add_model_class_to_graph.py create mode 100644 cognee/modules/data/extraction/knowledge_graph/establish_graph_topology.py create mode 100644 cognee/modules/data/extraction/knowledge_graph/expand_knowledge_graph.py create mode 100644 cognee/modules/data/extraction/texts.json create mode 100644 cognee/modules/data/processing/__init__.py create mode 100644 cognee/modules/data/processing/chunk_types/DocumentChunk.py create mode 100644 cognee/modules/data/processing/document_types/AudioDocument.py create mode 100644 cognee/modules/data/processing/document_types/Document.py create mode 100644 cognee/modules/data/processing/document_types/ImageDocument.py create mode 100644 cognee/modules/data/processing/document_types/PdfDocument.py create mode 100644 cognee/modules/data/processing/document_types/TextDocument.py create mode 100644 cognee/modules/data/processing/document_types/__init__.py create mode 100644 cognee/modules/data/processing/document_types/__tests__/PdfDocument.test.py create mode 100644 cognee/modules/data/processing/document_types/__tests__/artificial-inteligence.pdf create mode 100644 cognee/modules/data/processing/document_types/__tests__/soldiers-home.pdf create mode 100644 cognee/modules/data/processing/filter_affected_chunks.py create mode 100644 cognee/modules/data/processing/has_new_chunks.py create mode 100644 cognee/modules/data/processing/process_documents.py create mode 100644 cognee/modules/data/processing/remove_obsolete_chunks.py create mode 100644 cognee/modules/pipelines/Pipeline.py create mode 100644 cognee/modules/pipelines/__init__.py create mode 100644 cognee/modules/pipelines/models/Pipeline.py create mode 100644 cognee/modules/pipelines/models/PipelineTask.py create mode 100644 cognee/modules/pipelines/models/Task.py create mode 100644 cognee/modules/pipelines/operations/__init__.py create mode 100644 cognee/modules/pipelines/operations/__tests__/__index__.py create mode 100644 cognee/modules/pipelines/operations/__tests__/artificial-inteligence.v1.pdf create mode 100644 cognee/modules/pipelines/operations/__tests__/artificial-inteligence.v2.pdf create mode 100644 cognee/modules/pipelines/operations/__tests__/get_graph_url.py create mode 100644 cognee/modules/pipelines/operations/__tests__/run_tasks.test.py create mode 100644 cognee/modules/pipelines/operations/add_task.py create mode 100644 cognee/modules/pipelines/operations/run_parallel.py create mode 100644 cognee/modules/pipelines/operations/run_tasks.py create mode 100644 cognee/modules/pipelines/tasks/Task.py delete mode 100644 cognee/modules/search/graph/search_categories.py delete mode 100644 cognee/modules/search/graph/search_neighbour.py create mode 100644 cognee/modules/search/graph/search_similarity.py delete mode 100644 cognee/modules/search/vector/search_similarity.py create mode 100644 cognee/modules/search/vector/search_traverse.py create mode 100644 cognee/tests/test_data/artificial-intelligence.pdf delete mode 100644 docker-compose-vanilla.yml diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index 2eeca4d16..638536f8c 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -30,9 +30,9 @@ jobs: # Test all python versions on ubuntu only include: - python-version: "3.9.x" - os: "ubuntu-latest" + os: "ubuntu-22.04" - python-version: "3.10.x" - os: "ubuntu-latest" + os: "ubuntu-22.04" # - python-version: "3.12.x" # os: "ubuntu-latest" @@ -90,6 +90,12 @@ jobs: ENV: 'dev' run: poetry run python ./cognee/tests/test_library.py + - name: Clean up disk space + run: | + sudo rm -rf ~/.cache + sudo rm -rf /tmp/* + df -h + - name: Build with Poetry run: poetry build diff --git a/cognee-frontend/src/modules/ingestion/DataView/DataView.tsx b/cognee-frontend/src/modules/ingestion/DataView/DataView.tsx index 4df0a12a6..d9e66639e 100644 --- a/cognee-frontend/src/modules/ingestion/DataView/DataView.tsx +++ b/cognee-frontend/src/modules/ingestion/DataView/DataView.tsx @@ -15,7 +15,6 @@ export interface Data { name: string; filePath: string; mimeType: string; - keywords: string[]; } interface DatasetLike { @@ -113,9 +112,6 @@ export default function DataView({ datasetId, data, onClose, onDataAdd }: DataVi {dataItem.mimeType} - - {dataItem.keywords.join(", ")} - ))} diff --git a/cognee-frontend/src/modules/ingestion/addData.ts b/cognee-frontend/src/modules/ingestion/addData.ts index be7a35b2c..3087f5e7d 100644 --- a/cognee-frontend/src/modules/ingestion/addData.ts +++ b/cognee-frontend/src/modules/ingestion/addData.ts @@ -1,8 +1,9 @@ export default function addData(dataset: { id: string }, files: File[]) { const formData = new FormData(); + files.forEach((file) => { + formData.append('data', file, file.name); + }) formData.append('datasetId', dataset.id); - const file = files[0]; - formData.append('data', file, file.name); return fetch('http://0.0.0.0:8000/add', { method: 'POST', diff --git a/cognee-frontend/src/ui/Partials/SearchView/SearchView.tsx b/cognee-frontend/src/ui/Partials/SearchView/SearchView.tsx index 1d64de1be..d94c83004 100644 --- a/cognee-frontend/src/ui/Partials/SearchView/SearchView.tsx +++ b/cognee-frontend/src/ui/Partials/SearchView/SearchView.tsx @@ -33,8 +33,8 @@ export default function SearchView() { value: 'ADJACENT', label: 'Look for graph node\'s neighbors', }, { - value: 'CATEGORIES', - label: 'Search by categories (Comma separated categories)', + value: 'TRAVERSE', + label: 'Traverse through the graph and get knowledge', }]; const [searchType, setSearchType] = useState(searchOptions[0]); diff --git a/cognee/__init__.py b/cognee/__init__.py index 081b3d7f0..49a5d7f21 100644 --- a/cognee/__init__.py +++ b/cognee/__init__.py @@ -1,6 +1,6 @@ from .api.v1.config.config import config from .api.v1.add.add import add -from .api.v1.cognify.cognify import cognify +from .api.v1.cognify.cognify_v2 import cognify from .api.v1.datasets.datasets import datasets from .api.v1.search.search import search, SearchType from .api.v1.prune import prune diff --git a/cognee/api/client.py b/cognee/api/client.py index 94fb259be..196582b5d 100644 --- a/cognee/api/client.py +++ b/cognee/api/client.py @@ -2,9 +2,10 @@ import os import aiohttp import uvicorn -import asyncio import json +import asyncio import logging +import sentry_sdk from typing import Dict, Any, List, Union, Optional, Literal from typing_extensions import Annotated from fastapi import FastAPI, HTTPException, Form, File, UploadFile, Query @@ -19,7 +20,14 @@ logging.basicConfig( ) logger = logging.getLogger(__name__) -app = FastAPI(debug = True) +if os.getenv("ENV") == "prod": + sentry_sdk.init( + dsn = os.getenv("SENTRY_REPORTING_URL"), + traces_sample_rate = 1.0, + profiles_sample_rate = 1.0, + ) + +app = FastAPI(debug = os.getenv("ENV") != "prod") origins = [ "http://frontend:3000", @@ -69,10 +77,10 @@ async def delete_dataset(dataset_id: str): @app.get("/datasets/{dataset_id}/graph", response_model=list) async def get_dataset_graph(dataset_id: str): from cognee.shared.utils import render_graph - from cognee.infrastructure.databases.graph.get_graph_client import get_graph_client + from cognee.infrastructure.databases.graph import get_graph_engine try: - graph_client = await get_graph_client() + graph_client = await get_graph_engine() graph_url = await render_graph(graph_client.graph) return JSONResponse( @@ -95,7 +103,6 @@ async def get_dataset_data(dataset_id: str): dict( id=data["id"], name=f"{data['name']}.{data['extension']}", - keywords=data["keywords"].split("|"), filePath=data["file_path"], mimeType=data["mime_type"], ) @@ -129,8 +136,8 @@ class AddPayload(BaseModel): @app.post("/add", response_model=dict) async def add( + data: List[UploadFile], datasetId: str = Form(...), - data: List[UploadFile] = File(...), ): """ This endpoint is responsible for adding data to the graph.""" from cognee.api.v1.add import add as cognee_add @@ -177,17 +184,17 @@ class CognifyPayload(BaseModel): @app.post("/cognify", response_model=dict) async def cognify(payload: CognifyPayload): """ This endpoint is responsible for the cognitive processing of the content.""" - from cognee.api.v1.cognify.cognify import cognify as cognee_cognify + from cognee.api.v1.cognify.cognify_v2 import cognify as cognee_cognify try: await cognee_cognify(payload.datasets) return JSONResponse( - status_code=200, - content="OK" + status_code = 200, + content = "OK" ) except Exception as error: return JSONResponse( - status_code=409, - content={"error": str(error)} + status_code = 409, + content = {"error": str(error)} ) class SearchPayload(BaseModel): @@ -255,30 +262,13 @@ def start_api_server(host: str = "0.0.0.0", port: int = 8000): try: logger.info("Starting server at %s:%s", host, port) - from cognee.base_config import get_base_config from cognee.infrastructure.databases.relational import get_relationaldb_config - from cognee.infrastructure.databases.vector import get_vectordb_config - from cognee.infrastructure.databases.graph import get_graph_config - - cognee_directory_path = os.path.abspath(".cognee_system") - databases_directory_path = os.path.join(cognee_directory_path, "databases") - relational_config = get_relationaldb_config() - relational_config.db_path = databases_directory_path relational_config.create_engine() - vector_config = get_vectordb_config() - vector_config.vector_db_url = os.path.join(databases_directory_path, "cognee.lancedb") - - graph_config = get_graph_config() - graph_config.graph_file_path = os.path.join(databases_directory_path, "cognee.graph") - - base_config = get_base_config() - data_directory_path = os.path.abspath(".data_storage") - base_config.data_root_directory = data_directory_path - - from cognee.modules.data.deletion import prune_system - asyncio.run(prune_system()) + from cognee.modules.data.deletion import prune_system, prune_data + asyncio.run(prune_data()) + asyncio.run(prune_system(metadata = True)) uvicorn.run(app, host = host, port = port) except Exception as e: diff --git a/cognee/api/v1/add/add.py b/cognee/api/v1/add/add.py index 995465bfc..e5f120573 100644 --- a/cognee/api/v1/add/add.py +++ b/cognee/api/v1/add/add.py @@ -97,7 +97,6 @@ async def add_files(file_paths: List[str], dataset_name: str): "file_path": file_metadata["file_path"], "extension": file_metadata["extension"], "mime_type": file_metadata["mime_type"], - "keywords": "|".join(file_metadata["keywords"]), } run_info = pipeline.run( diff --git a/cognee/api/v1/cognify/cognify.py b/cognee/api/v1/cognify/cognify.py index 408b92e76..632d52c04 100644 --- a/cognee/api/v1/cognify/cognify.py +++ b/cognee/api/v1/cognify/cognify.py @@ -6,21 +6,19 @@ import nltk from asyncio import Lock from nltk.corpus import stopwords -from cognee.infrastructure.data.chunking.LangchainChunkingEngine import LangchainChunkEngine from cognee.infrastructure.data.chunking.get_chunking_engine import get_chunk_engine from cognee.infrastructure.databases.graph.config import get_graph_config from cognee.infrastructure.databases.vector.embeddings.LiteLLMEmbeddingEngine import LiteLLMEmbeddingEngine from cognee.modules.cognify.graph.add_node_connections import group_nodes_by_layer, \ graph_ready_output, connect_nodes_in_graph -from cognee.modules.cognify.graph.add_data_chunks import add_data_chunks, add_data_chunks_basic_rag +from cognee.modules.cognify.graph.add_data_chunks import add_data_chunks from cognee.modules.cognify.graph.add_document_node import add_document_node from cognee.modules.cognify.graph.add_classification_nodes import add_classification_nodes from cognee.modules.cognify.graph.add_cognitive_layer_graphs import add_cognitive_layer_graphs from cognee.modules.cognify.graph.add_summary_nodes import add_summary_nodes from cognee.modules.cognify.llm.resolve_cross_graph_references import resolve_cross_graph_references -from cognee.infrastructure.databases.graph.get_graph_client import get_graph_client +from cognee.infrastructure.databases.graph import get_graph_engine from cognee.modules.cognify.graph.add_cognitive_layers import add_cognitive_layers -# from cognee.modules.cognify.graph.initialize_graph import initialize_graph from cognee.infrastructure.files.utils.guess_file_type import guess_file_type, FileTypeException from cognee.infrastructure.files.utils.extract_text_from_file import extract_text_from_file from cognee.modules.data.get_content_categories import get_content_categories @@ -49,9 +47,7 @@ async def cognify(datasets: Union[str, List[str]] = None): stopwords.ensure_loaded() create_task_status_table() - # graph_config = get_graph_config() - # graph_db_type = graph_config.graph_engine - graph_client = await get_graph_client() + graph_client = await get_graph_engine() relational_config = get_relationaldb_config() db_engine = relational_config.database_engine @@ -89,8 +85,8 @@ async def cognify(datasets: Union[str, List[str]] = None): added_datasets = db_engine.get_datasets() - dataset_files = [] # datasets is a dataset name string + dataset_files = [] dataset_name = datasets.replace(".", "_").replace(" ", "_") for added_dataset in added_datasets: @@ -145,10 +141,8 @@ async def cognify(datasets: Union[str, List[str]] = None): batch_size = 20 file_count = 0 files_batch = [] - from cognee.infrastructure.databases.graph.config import get_graph_config - graph_config = get_graph_config() - graph_topology = graph_config.graph_model + graph_config = get_graph_config() if graph_config.infer_graph_topology and graph_config.graph_topology_task: from cognee.modules.topology.topology import TopologyEngine @@ -173,8 +167,8 @@ async def cognify(datasets: Union[str, List[str]] = None): else: document_id = await add_document_node( graph_client, - parent_node_id=file_metadata['id'], - document_metadata=file_metadata, + parent_node_id = file_metadata['id'], + document_metadata = file_metadata, ) files_batch.append((dataset_name, file_metadata, document_id)) @@ -196,7 +190,7 @@ async def process_text(chunk_collection: str, chunk_id: str, input_text: str, fi print(f"Processing chunk ({chunk_id}) from document ({file_metadata['id']}).") graph_config = get_graph_config() - graph_client = await get_graph_client() + graph_client = await get_graph_engine() graph_topology = graph_config.graph_model if graph_topology == SourceCodeGraph: @@ -206,8 +200,6 @@ async def process_text(chunk_collection: str, chunk_id: str, input_text: str, fi else: classified_categories = [{"data_type": "text", "category_name": "Unclassified text"}] - # await add_label_nodes(graph_client, document_id, chunk_id, file_metadata["keywords"].split("|")) - await add_classification_nodes( graph_client, parent_node_id = document_id, @@ -271,10 +263,10 @@ if __name__ == "__main__": # await prune.prune_system() # # # from cognee.api.v1.add import add - # data_directory_path = os.path.abspath("../../../.data") + # data_directory_path = os.path.abspath("../../.data") # # print(data_directory_path) # # config.data_root_directory(data_directory_path) - # # cognee_directory_path = os.path.abspath("../.cognee_system") + # # cognee_directory_path = os.path.abspath(".cognee_system") # # config.system_root_directory(cognee_directory_path) # # await add("data://" +data_directory_path, "example") diff --git a/cognee/api/v1/cognify/cognify_v2.py b/cognee/api/v1/cognify/cognify_v2.py new file mode 100644 index 000000000..e10680f19 --- /dev/null +++ b/cognee/api/v1/cognify/cognify_v2.py @@ -0,0 +1,139 @@ +import asyncio +import logging +from typing import Union + +from cognee.infrastructure.databases.graph import get_graph_config +from cognee.modules.cognify.config import get_cognify_config +from cognee.infrastructure.databases.relational.config import get_relationaldb_config +from cognee.modules.data.processing.document_types.AudioDocument import AudioDocument +from cognee.modules.data.processing.document_types.ImageDocument import ImageDocument +from cognee.shared.data_models import KnowledgeGraph +from cognee.modules.data.processing.document_types import PdfDocument, TextDocument +from cognee.modules.cognify.vector import save_data_chunks +from cognee.modules.data.processing.process_documents import process_documents +from cognee.modules.classification.classify_text_chunks import classify_text_chunks +from cognee.modules.data.extraction.data_summary.summarize_text_chunks import summarize_text_chunks +from cognee.modules.data.processing.filter_affected_chunks import filter_affected_chunks +from cognee.modules.data.processing.remove_obsolete_chunks import remove_obsolete_chunks +from cognee.modules.data.extraction.knowledge_graph.expand_knowledge_graph import expand_knowledge_graph +from cognee.modules.data.extraction.knowledge_graph.establish_graph_topology import establish_graph_topology +from cognee.modules.pipelines.tasks.Task import Task +from cognee.modules.pipelines import run_tasks, run_tasks_parallel +from cognee.modules.tasks import create_task_status_table, update_task_status, get_task_status + +logger = logging.getLogger("cognify.v2") + +update_status_lock = asyncio.Lock() + +async def cognify(datasets: Union[str, list[str]] = None, root_node_id: str = None): + relational_config = get_relationaldb_config() + db_engine = relational_config.database_engine + create_task_status_table() + + if datasets is None or len(datasets) == 0: + return await cognify(db_engine.get_datasets()) + + + async def run_cognify_pipeline(dataset_name: str, files: list[dict]): + async with update_status_lock: + task_status = get_task_status([dataset_name]) + + if dataset_name in task_status and task_status[dataset_name] == "DATASET_PROCESSING_STARTED": + logger.info(f"Dataset {dataset_name} is being processed.") + return + + update_task_status(dataset_name, "DATASET_PROCESSING_STARTED") + try: + cognee_config = get_cognify_config() + graph_config = get_graph_config() + root_node_id = None + + if graph_config.infer_graph_topology and graph_config.graph_topology_task: + from cognee.modules.topology.topology import TopologyEngine + topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) + root_node_id = await topology_engine.add_graph_topology(files = files) + elif graph_config.infer_graph_topology and not graph_config.infer_graph_topology: + from cognee.modules.topology.topology import TopologyEngine + topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) + await topology_engine.add_graph_topology(graph_config.topology_file_path) + elif not graph_config.graph_topology_task: + root_node_id = "ROOT" + + tasks = [ + Task(process_documents, parent_node_id = root_node_id, task_config = { "batch_size": 10 }), # Classify documents and save them as a nodes in graph db, extract text chunks based on the document type + Task(establish_graph_topology, topology_model = KnowledgeGraph), # Set the graph topology for the document chunk data + Task(expand_knowledge_graph, graph_model = KnowledgeGraph), # Generate knowledge graphs from the document chunks and attach it to chunk nodes + Task(filter_affected_chunks, collection_name = "chunks"), # Find all affected chunks, so we don't process unchanged chunks + Task( + save_data_chunks, + collection_name = "chunks", + ), # Save the document chunks in vector db and as nodes in graph db (connected to the document node and between each other) + run_tasks_parallel([ + Task( + summarize_text_chunks, + summarization_model = cognee_config.summarization_model, + collection_name = "chunk_summaries", + ), # Summarize the document chunks + Task( + classify_text_chunks, + classification_model = cognee_config.classification_model, + ), + ]), + Task(remove_obsolete_chunks), # Remove the obsolete document chunks. + ] + + pipeline = run_tasks(tasks, [ + PdfDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "pdf" else + AudioDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "audio" else + ImageDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "image" else + TextDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) + for file in files + ]) + + async for result in pipeline: + print(result) + + update_task_status(dataset_name, "DATASET_PROCESSING_FINISHED") + except Exception as error: + update_task_status(dataset_name, "DATASET_PROCESSING_ERROR") + raise error + + + existing_datasets = db_engine.get_datasets() + + awaitables = [] + + + # dataset_files = [] + # dataset_name = datasets.replace(".", "_").replace(" ", "_") + + # for added_dataset in existing_datasets: + # if dataset_name in added_dataset: + # dataset_files.append((added_dataset, db_engine.get_files_metadata(added_dataset))) + + for dataset in datasets: + if dataset in existing_datasets: + # for file_metadata in files: + # if root_node_id is None: + # root_node_id=file_metadata['id'] + awaitables.append(run_cognify_pipeline(dataset, db_engine.get_files_metadata(dataset))) + + return await asyncio.gather(*awaitables) + + +# +# if __name__ == "__main__": +# from cognee.api.v1.add import add +# from cognee.api.v1.datasets.datasets import datasets +# +# +# async def aa(): +# await add("TEXT ABOUT NLP AND MONKEYS") +# +# print(datasets.discover_datasets()) +# +# return + + + + # asyncio.run(cognify()) diff --git a/cognee/api/v1/config/config.py b/cognee/api/v1/config/config.py index dd8e4e53e..b284c622f 100644 --- a/cognee/api/v1/config/config.py +++ b/cognee/api/v1/config/config.py @@ -16,6 +16,9 @@ class config(): relational_config.db_path = databases_directory_path relational_config.create_engine() + graph_config = get_graph_config() + graph_config.graph_file_path = os.path.join(databases_directory_path, "cognee.graph") + vector_config = get_vectordb_config() if vector_config.vector_engine_provider == "lancedb": vector_config.vector_db_url = os.path.join(databases_directory_path, "cognee.lancedb") diff --git a/cognee/api/v1/prune/prune.py b/cognee/api/v1/prune/prune.py index ae042627d..4237ac58e 100644 --- a/cognee/api/v1/prune/prune.py +++ b/cognee/api/v1/prune/prune.py @@ -1,17 +1,13 @@ -from cognee.modules.data.deletion import prune_system -from cognee.base_config import get_base_config -from cognee.infrastructure.files.storage import LocalStorage +from cognee.modules.data.deletion import prune_system, prune_data class prune(): @staticmethod async def prune_data(): - base_config = get_base_config() - data_root_directory = base_config.data_root_directory - LocalStorage.remove_all(data_root_directory) + await prune_data() @staticmethod - async def prune_system(graph = True, vector = True): - await prune_system(graph, vector) + async def prune_system(graph = True, vector = True, metadata = False): + await prune_system(graph, vector, metadata) if __name__ == "__main__": import asyncio diff --git a/cognee/api/v1/search/search.py b/cognee/api/v1/search/search.py index 08f311f62..8cec061b3 100644 --- a/cognee/api/v1/search/search.py +++ b/cognee/api/v1/search/search.py @@ -6,19 +6,16 @@ from pydantic import BaseModel, field_validator from cognee.modules.search.graph import search_cypher from cognee.modules.search.graph.search_adjacent import search_adjacent -from cognee.modules.search.vector.search_similarity import search_similarity -from cognee.modules.search.graph.search_categories import search_categories -from cognee.modules.search.graph.search_neighbour import search_neighbour +from cognee.modules.search.vector.search_traverse import search_traverse from cognee.modules.search.graph.search_summary import search_summary -from cognee.infrastructure.databases.graph.get_graph_client import get_graph_client +from cognee.modules.search.graph.search_similarity import search_similarity +from cognee.infrastructure.databases.graph.get_graph_engine import get_graph_engine from cognee.shared.utils import send_telemetry -from cognee.infrastructure.databases.graph.config import get_graph_config class SearchType(Enum): ADJACENT = "ADJACENT" + TRAVERSE = "TRAVERSE" SIMILARITY = "SIMILARITY" - CATEGORIES = "CATEGORIES" - NEIGHBOR = "NEIGHBOR" SUMMARY = "SUMMARY" SUMMARY_CLASSIFICATION = "SUMMARY_CLASSIFICATION" NODE_CLASSIFICATION = "NODE_CLASSIFICATION" @@ -49,18 +46,15 @@ async def search(search_type: str, params: Dict[str, Any]) -> List: async def specific_search(query_params: List[SearchParameters]) -> List: - graph_config = get_graph_config() - graph_client = await get_graph_client(graph_config.graph_database_provider) + graph_client = await get_graph_engine() graph = graph_client.graph search_functions: Dict[SearchType, Callable] = { SearchType.ADJACENT: search_adjacent, - SearchType.SIMILARITY: search_similarity, - SearchType.CATEGORIES: search_categories, - SearchType.NEIGHBOR: search_neighbour, SearchType.SUMMARY: search_summary, - SearchType.CYPHER: search_cypher - + SearchType.CYPHER: search_cypher, + SearchType.TRAVERSE: search_traverse, + SearchType.SIMILARITY: search_similarity, } results = [] @@ -103,7 +97,7 @@ if __name__ == "__main__": # SearchType.SIMILARITY: {'query': 'your search query here'} # } # async def main(): -# graph_client = get_graph_client(GraphDBType.NETWORKX) +# graph_client = get_graph_engine() # await graph_client.load_graph_from_file() # graph = graph_client.graph diff --git a/cognee/base_config.py b/cognee/base_config.py index 2dcd859e7..d2245ef6e 100644 --- a/cognee/base_config.py +++ b/cognee/base_config.py @@ -5,7 +5,7 @@ from cognee.root_dir import get_absolute_path from cognee.shared.data_models import MonitoringTool class BaseConfig(BaseSettings): - data_root_directory: str = get_absolute_path(".data") + data_root_directory: str = get_absolute_path(".data_storage") monitoring_tool: object = MonitoringTool.LANGFUSE graphistry_username: Optional[str] = None graphistry_password: Optional[str] = None diff --git a/cognee/infrastructure/data/chunking/create_chunking_engine.py b/cognee/infrastructure/data/chunking/create_chunking_engine.py index 27fe5d237..5cd0d9077 100644 --- a/cognee/infrastructure/data/chunking/create_chunking_engine.py +++ b/cognee/infrastructure/data/chunking/create_chunking_engine.py @@ -16,17 +16,15 @@ def create_chunking_engine(config: ChunkingConfig): chunk_size=config["chunk_size"], chunk_overlap=config["chunk_overlap"], chunk_strategy=config["chunk_strategy"], - - ) elif config["chunk_engine"] == ChunkEngine.DEFAULT_ENGINE: - from cognee.infrastructure.data.chunking.DefaultChunkEngine import DefaultChunkEngine + from cognee.infrastructure.data.chunking.DefaultChunkEngine import DefaultChunkEngine - return DefaultChunkEngine( - chunk_size=config["chunk_size"], - chunk_overlap=config["chunk_overlap"], - chunk_strategy=config["chunk_strategy"], - ) + return DefaultChunkEngine( + chunk_size=config["chunk_size"], + chunk_overlap=config["chunk_overlap"], + chunk_strategy=config["chunk_strategy"], + ) elif config["chunk_engine"] == ChunkEngine.HAYSTACK_ENGINE: from cognee.infrastructure.data.chunking.HaystackChunkEngine import HaystackChunkEngine diff --git a/cognee/infrastructure/data/chunking/get_chunking_engine.py b/cognee/infrastructure/data/chunking/get_chunking_engine.py index e9b2c4a92..d188ffa9b 100644 --- a/cognee/infrastructure/data/chunking/get_chunking_engine.py +++ b/cognee/infrastructure/data/chunking/get_chunking_engine.py @@ -3,4 +3,4 @@ from .config import get_chunk_config from .create_chunking_engine import create_chunking_engine def get_chunk_engine(): - return create_chunking_engine(get_chunk_config().to_dict()) \ No newline at end of file + return create_chunking_engine(get_chunk_config().to_dict()) diff --git a/cognee/infrastructure/databases/graph/__init__.py b/cognee/infrastructure/databases/graph/__init__.py index 911a65da4..68ab3b409 100644 --- a/cognee/infrastructure/databases/graph/__init__.py +++ b/cognee/infrastructure/databases/graph/__init__.py @@ -1 +1,2 @@ from .config import get_graph_config +from .get_graph_engine import get_graph_engine diff --git a/cognee/infrastructure/databases/graph/config.py b/cognee/infrastructure/databases/graph/config.py index d20d997eb..dfaea49cb 100644 --- a/cognee/infrastructure/databases/graph/config.py +++ b/cognee/infrastructure/databases/graph/config.py @@ -21,7 +21,7 @@ class GraphConfig(BaseSettings): graph_model: object = KnowledgeGraph graph_topology_task: bool = False graph_topology: object = KnowledgeGraph - infer_graph_topology: bool = True + infer_graph_topology: bool = False topology_file_path: str = os.path.join( os.path.join(get_absolute_path(".cognee_system"), "databases"), "graph_topology.json" diff --git a/cognee/infrastructure/databases/graph/falkordb/adapter.py b/cognee/infrastructure/databases/graph/falkordb/adapter.py index 0765fe323..2c9dbbea9 100644 --- a/cognee/infrastructure/databases/graph/falkordb/adapter.py +++ b/cognee/infrastructure/databases/graph/falkordb/adapter.py @@ -70,8 +70,6 @@ class FalcorDBAdapter(GraphDBInterface): return await self.query(query, params) async def add_nodes(self, nodes: list[tuple[str, dict[str, Any]]]) -> None: - # nodes_data = [] - for node in nodes: node_id, node_properties = node node_id = node_id.replace(":", "_") @@ -112,18 +110,27 @@ class FalcorDBAdapter(GraphDBInterface): query = """MATCH (node) WHERE node.layer_id IS NOT NULL RETURN node""" - return [result['node'] for result in (await self.query(query))] + return [result["node"] for result in (await self.query(query))] async def extract_node(self, node_id: str): - query= """ - MATCH(node {id: $node_id}) - RETURN node - """ - - results = [node['node'] for node in (await self.query(query, dict(node_id = node_id)))] + results = self.extract_nodes([node_id]) return results[0] if len(results) > 0 else None + async def extract_nodes(self, node_ids: List[str]): + query = """ + UNWIND $node_ids AS id + MATCH (node {id: id}) + RETURN node""" + + params = { + "node_ids": node_ids + } + + results = await self.query(query, params) + + return results + async def delete_node(self, node_id: str): node_id = id.replace(":", "_") diff --git a/cognee/infrastructure/databases/graph/get_graph_client.py b/cognee/infrastructure/databases/graph/get_graph_engine.py similarity index 87% rename from cognee/infrastructure/databases/graph/get_graph_client.py rename to cognee/infrastructure/databases/graph/get_graph_engine.py index 05be21a70..465b09b6b 100644 --- a/cognee/infrastructure/databases/graph/get_graph_client.py +++ b/cognee/infrastructure/databases/graph/get_graph_engine.py @@ -1,12 +1,11 @@ """Factory function to get the appropriate graph client based on the graph type.""" -from cognee.shared.data_models import GraphDBType from .config import get_graph_config from .graph_db_interface import GraphDBInterface from .networkx.adapter import NetworkXAdapter -async def get_graph_client(graph_type: GraphDBType=None, graph_file_name: str = None) -> GraphDBInterface : +async def get_graph_engine() -> GraphDBInterface : """Factory function to get the appropriate graph client based on the graph type.""" config = get_graph_config() @@ -34,8 +33,10 @@ async def get_graph_client(graph_type: GraphDBType=None, graph_file_name: str = ) except: pass + graph_client = NetworkXAdapter(filename = config.graph_file_path) - if (graph_client.graph is None): + + if graph_client.graph is None: await graph_client.load_graph_from_file() return graph_client diff --git a/cognee/infrastructure/databases/graph/graph_db_interface.py b/cognee/infrastructure/databases/graph/graph_db_interface.py index c47300d47..37aae5c95 100644 --- a/cognee/infrastructure/databases/graph/graph_db_interface.py +++ b/cognee/infrastructure/databases/graph/graph_db_interface.py @@ -25,12 +25,24 @@ class GraphDBInterface(Protocol): node_id: str ): raise NotImplementedError + @abstractmethod + async def delete_nodes( + self, + node_ids: list[str] + ): raise NotImplementedError + @abstractmethod async def extract_node( self, node_id: str ): raise NotImplementedError + @abstractmethod + async def extract_nodes( + self, + node_ids: list[str] + ): raise NotImplementedError + @abstractmethod async def add_edge( self, diff --git a/cognee/infrastructure/databases/graph/neo4j_driver/adapter.py b/cognee/infrastructure/databases/graph/neo4j_driver/adapter.py index f687d29fc..51568973a 100644 --- a/cognee/infrastructure/databases/graph/neo4j_driver/adapter.py +++ b/cognee/infrastructure/databases/graph/neo4j_driver/adapter.py @@ -1,6 +1,7 @@ """ Neo4j Adapter for Graph Database""" import json import logging +import asyncio from typing import Optional, Any, List, Dict from contextlib import asynccontextmanager from neo4j import AsyncSession @@ -56,6 +57,7 @@ class Neo4jAdapter(GraphDBInterface): if "name" not in serialized_properties: serialized_properties["name"] = node_id + query = f"""MERGE (node:`{node_id}` {{id: $node_id}}) ON CREATE SET node += $properties RETURN ID(node) AS internal_id, node.id AS nodeId""" @@ -68,16 +70,22 @@ class Neo4jAdapter(GraphDBInterface): return await self.query(query, params) async def add_nodes(self, nodes: list[tuple[str, dict[str, Any]]]) -> None: - # nodes_data = [] + query = """ + UNWIND $nodes AS node + MERGE (n {id: node.node_id}) + ON CREATE SET n += node.properties + WITH n, node.node_id AS label + CALL apoc.create.addLabels(n, [label]) YIELD node AS labeledNode + RETURN ID(labeledNode) AS internal_id, labeledNode.id AS nodeId + """ - for node in nodes: - node_id, node_properties = node - node_id = node_id.replace(":", "_") + nodes = [{ + "node_id": node_id, + "properties": self.serialize_properties(node_properties), + } for (node_id, node_properties) in nodes] - await self.add_node( - node_id = node_id, - node_properties = node_properties, - ) + results = await self.query(query, dict(nodes = nodes)) + return results async def extract_node_description(self, node_id: str): query = """MATCH (n)-[r]->(m) @@ -111,15 +119,24 @@ class Neo4jAdapter(GraphDBInterface): return [result["node"] for result in (await self.query(query))] async def extract_node(self, node_id: str): - query= """ - MATCH(node {id: $node_id}) - RETURN node - """ - - results = [node["node"] for node in (await self.query(query, dict(node_id = node_id)))] + results = await self.extract_nodes([node_id]) return results[0] if len(results) > 0 else None + async def extract_nodes(self, node_ids: List[str]): + query = """ + UNWIND $node_ids AS id + MATCH (node {id: id}) + RETURN node""" + + params = { + "node_ids": node_ids + } + + results = await self.query(query, params) + + return [result["node"] for result in results] + async def delete_node(self, node_id: str): node_id = id.replace(":", "_") @@ -128,6 +145,18 @@ class Neo4jAdapter(GraphDBInterface): return await self.query(query, params) + async def delete_nodes(self, node_ids: list[str]) -> None: + query = """ + UNWIND $node_ids AS id + MATCH (node {id: id}) + DETACH DELETE node""" + + params = { + "node_ids": node_ids + } + + return await self.query(query, params) + async def add_edge(self, from_node: str, to_node: str, relationship_name: str, edge_properties: Optional[Dict[str, Any]] = {}): serialized_properties = self.serialize_properties(edge_properties) from_node = from_node.replace(":", "_") @@ -150,19 +179,75 @@ class Neo4jAdapter(GraphDBInterface): async def add_edges(self, edges: list[tuple[str, str, str, dict[str, Any]]]) -> None: - # edges_data = [] + query = """ + UNWIND $edges AS edge + MATCH (from_node {id: edge.from_node}) + MATCH (to_node {id: edge.to_node}) + CALL apoc.create.relationship(from_node, edge.relationship_name, edge.properties, to_node) YIELD rel + RETURN rel + """ - for edge in edges: - from_node, to_node, relationship_name, edge_properties = edge - from_node = from_node.replace(":", "_") - to_node = to_node.replace(":", "_") + edges = [{ + "from_node": edge[0], + "to_node": edge[1], + "relationship_name": edge[2], + "properties": { + **(edge[3] if edge[3] else {}), + "source_node_id": edge[0], + "target_node_id": edge[1], + }, + } for edge in edges] - await self.add_edge( - from_node = from_node, - to_node = to_node, - relationship_name = relationship_name, - edge_properties = edge_properties - ) + results = await self.query(query, dict(edges = edges)) + return results + + async def get_edges(self, node_id: str): + query = """ + MATCH (n {id: $node_id})-[r]-(m) + RETURN n, r, m + """ + + results = await self.query(query, dict(node_id = node_id)) + + return [(result["n"]["id"], result["m"]["id"], {"relationship_name": result["r"][1]}) for result in results] + + async def get_disconnected_nodes(self) -> list[str]: + # return await self.query( + # "MATCH (node) WHERE NOT (node)<-[:*]-() RETURN node.id as id", + # ) + query = """ + // Step 1: Collect all nodes + MATCH (n) + WITH COLLECT(n) AS nodes + + // Step 2: Find all connected components + WITH nodes + CALL { + WITH nodes + UNWIND nodes AS startNode + MATCH path = (startNode)-[*]-(connectedNode) + WITH startNode, COLLECT(DISTINCT connectedNode) AS component + RETURN component + } + + // Step 3: Aggregate components + WITH COLLECT(component) AS components + + // Step 4: Identify the largest connected component + UNWIND components AS component + WITH component + ORDER BY SIZE(component) DESC + LIMIT 1 + WITH component AS largestComponent + + // Step 5: Find nodes not in the largest connected component + MATCH (n) + WHERE NOT n IN largestComponent + RETURN COLLECT(ID(n)) AS ids + """ + + results = await self.query(query) + return results[0]["ids"] if len(results) > 0 else [] async def filter_nodes(self, search_criteria): @@ -170,10 +255,99 @@ class Neo4jAdapter(GraphDBInterface): WHERE node.id CONTAINS '{search_criteria}' RETURN node""" - return await self.query(query) + async def get_predecessor_ids(self, node_id: str, edge_label: str = None) -> list[str]: + if edge_label is not None: + query = """ + MATCH (node:`{node_id}`)-[r:`{edge_label}`]->(predecessor) + RETURN predecessor.id AS id + """ + + results = await self.query( + query, + dict( + node_id = node_id, + edge_label = edge_label, + ) + ) + + return [result["id"] for result in results] + else: + query = """ + MATCH (node:`{node_id}`)-[r]->(predecessor) + RETURN predecessor.id AS id + """ + + results = await self.query( + query, + dict( + node_id = node_id, + ) + ) + + return [result["id"] for result in results] + + async def get_successor_ids(self, node_id: str, edge_label: str = None) -> list[str]: + if edge_label is not None: + query = """ + MATCH (node:`{node_id}`)<-[r:`{edge_label}`]-(successor) + RETURN successor.id AS id + """ + + results = await self.query( + query, + dict( + node_id = node_id, + edge_label = edge_label, + ), + ) + + return [result["id"] for result in results] + else: + query = """ + MATCH (node:`{node_id}`)<-[r]-(successor) + RETURN successor.id AS id + """ + + results = await self.query( + query, + dict( + node_id = node_id, + ) + ) + + return [result["id"] for result in results] + + async def get_neighbours(self, node_id: str) -> list[str]: + results = await asyncio.gather(*[self.get_predecessor_ids(node_id)], self.get_successor_ids(node_id)) + + return [*results[0], *results[1]] + + async def remove_connection_to_predecessors_of(self, node_ids: list[str], edge_label: str) -> None: + query = f""" + UNWIND $node_ids AS id + MATCH (node:`{id}`)-[r:{edge_label}]->(predecessor) + DELETE r; + """ + + params = { "node_ids": node_ids } + + return await self.query(query, params) + + async def remove_connection_to_successors_of(self, node_ids: list[str], edge_label: str) -> None: + query = f""" + UNWIND $node_ids AS id + MATCH (node:`{id}`)<-[r:{edge_label}]-(successor) + DELETE r; + """ + + params = { "node_ids": node_ids } + + return await self.query(query, params) + + async def delete_graph(self): query = """MATCH (node) DETACH DELETE node;""" @@ -186,3 +360,25 @@ class Neo4jAdapter(GraphDBInterface): if isinstance(property_value, (dict, list)) else property_value for property_key, property_value in properties.items() } + + async def get_graph_data(self): + query = "MATCH (n) RETURN ID(n) AS id, labels(n) AS labels, properties(n) AS properties" + result = await self.query(query) + nodes = [( + record["properties"]["id"], + record["properties"], + ) for record in result] + + query = """ + MATCH (n)-[r]->(m) + RETURN ID(n) AS source, ID(m) AS target, TYPE(r) AS type, properties(r) AS properties + """ + result = await self.query(query) + edges = [( + record["properties"]["source_node_id"], + record["properties"]["target_node_id"], + record["type"], + record["properties"], + ) for record in result] + + return (nodes, edges) diff --git a/cognee/infrastructure/databases/graph/networkx/adapter.py b/cognee/infrastructure/databases/graph/networkx/adapter.py index d5a8da0b0..848758867 100644 --- a/cognee/infrastructure/databases/graph/networkx/adapter.py +++ b/cognee/infrastructure/databases/graph/networkx/adapter.py @@ -44,7 +44,7 @@ class NetworkXAdapter(GraphDBInterface): async def get_graph(self): return self.graph - + async def add_edge( self, from_node: str, @@ -62,12 +62,31 @@ class NetworkXAdapter(GraphDBInterface): self.graph.add_edges_from(edges) await self.save_graph_to_file(self.filename) + async def get_edges(self, node_id: str): + return list(self.graph.in_edges(node_id, data = True)) + list(self.graph.out_edges(node_id, data = True)) + async def delete_node(self, node_id: str) -> None: """Asynchronously delete a node from the graph if it exists.""" if self.graph.has_node(id): self.graph.remove_node(id) await self.save_graph_to_file(self.filename) + async def delete_nodes(self, node_ids: List[str]) -> None: + self.graph.remove_nodes_from(node_ids) + await self.save_graph_to_file(self.filename) + + async def get_disconnected_nodes(self) -> List[str]: + connected_components = list(nx.weakly_connected_components(self.graph)) + + disconnected_nodes = [] + biggest_subgraph = max(connected_components, key = len) + + for component in connected_components: + if component != biggest_subgraph: + disconnected_nodes.extend(list(component)) + + return disconnected_nodes + async def extract_node_description(self, node_id: str) -> Dict[str, Any]: descriptions = [] @@ -98,11 +117,69 @@ class NetworkXAdapter(GraphDBInterface): async def extract_node(self, node_id: str) -> dict: if self.graph.has_node(node_id): - return self.graph.nodes[node_id] return None + async def extract_nodes(self, node_ids: List[str]) -> List[dict]: + return [self.graph.nodes[node_id] for node_id in node_ids if self.graph.has_node(node_id)] + + async def get_predecessor_ids(self, node_id: str, edge_label: str = None) -> list: + if self.graph.has_node(node_id): + if edge_label is None: + return list(self.graph.predecessors(node_id)) + + nodes = [] + + for predecessor_id in list(self.graph.predecessors(node_id)): + if self.graph.has_edge(predecessor_id, node_id, edge_label): + nodes.append(predecessor_id) + + return nodes + + async def get_successor_ids(self, node_id: str, edge_label: str = None) -> list: + if self.graph.has_node(node_id): + if edge_label is None: + return list(self.graph.successors(node_id)) + + nodes = [] + + for successor_id in list(self.graph.successors(node_id)): + if self.graph.has_edge(node_id, successor_id, edge_label): + nodes.append(successor_id) + + return nodes + + async def get_neighbours(self, node_id: str) -> list: + if not self.graph.has_node(node_id): + return [] + + neighbour_ids = list(self.graph.neighbors(node_id)) + + if len(neighbour_ids) == 0: + return [] + + nodes = await self.extract_nodes(neighbour_ids) + + return nodes + + async def remove_connection_to_predecessors_of(self, node_ids: list[str], edge_label: str) -> None: + for node_id in node_ids: + if self.graph.has_node(node_id): + for predecessor_id in list(self.graph.predecessors(node_id)): + if self.graph.has_edge(predecessor_id, node_id, edge_label): + self.graph.remove_edge(predecessor_id, node_id, edge_label) + + await self.save_graph_to_file(self.filename) + + async def remove_connection_to_successors_of(self, node_ids: list[str], edge_label: str) -> None: + for node_id in node_ids: + if self.graph.has_node(node_id): + for successor_id in list(self.graph.successors(node_id)): + if self.graph.has_edge(node_id, successor_id, edge_label): + self.graph.remove_edge(node_id, successor_id, edge_label) + + await self.save_graph_to_file(self.filename) async def save_graph_to_file(self, file_path: str=None) -> None: """Asynchronously save the graph to a file in JSON format.""" @@ -114,6 +191,7 @@ class NetworkXAdapter(GraphDBInterface): async with aiofiles.open(file_path, "w") as file: await file.write(json.dumps(graph_data)) + async def load_graph_from_file(self, file_path: str = None): """Asynchronously load the graph from a file in JSON format.""" if file_path == self.filename: diff --git a/cognee/infrastructure/databases/relational/duckdb/DuckDBAdapter.py b/cognee/infrastructure/databases/relational/duckdb/DuckDBAdapter.py index 4e136b950..1a0fbde3e 100644 --- a/cognee/infrastructure/databases/relational/duckdb/DuckDBAdapter.py +++ b/cognee/infrastructure/databases/relational/duckdb/DuckDBAdapter.py @@ -2,10 +2,9 @@ import duckdb import os class DuckDBAdapter(): def __init__(self, db_path: str, db_name: str): + self.db_location = os.path.abspath(os.path.join(db_path, db_name)) - db_location = os.path.abspath(os.path.join(db_path, db_name)) - - self.get_connection = lambda: duckdb.connect(db_location) + self.get_connection = lambda: duckdb.connect(self.db_location) def get_datasets(self): with self.get_connection() as connection: @@ -20,7 +19,7 @@ class DuckDBAdapter(): def get_files_metadata(self, dataset_name: str): with self.get_connection() as connection: - return connection.sql(f"SELECT id, name, file_path, extension, mime_type, keywords FROM {dataset_name}.file_metadata;").to_df().to_dict("records") + return connection.sql(f"SELECT id, name, file_path, extension, mime_type FROM {dataset_name}.file_metadata;").to_df().to_dict("records") def create_table(self, schema_name: str, table_name: str, table_config: list[dict]): fields_query_parts = [] @@ -163,3 +162,11 @@ class DuckDBAdapter(): connection.sql(select_data_sql) drop_data_sql = "DROP TABLE cognify;" connection.sql(drop_data_sql) + + def delete_database(self): + from cognee.infrastructure.files.storage import LocalStorage + + LocalStorage.remove(self.db_location) + + if LocalStorage.file_exists(self.db_location + ".wal"): + LocalStorage.remove(self.db_location + ".wal") diff --git a/cognee/infrastructure/databases/vector/falkordb/FalkorDBAdapter.py b/cognee/infrastructure/databases/vector/falkordb/FalkorDBAdapter.py index 29f4dd607..563219fec 100644 --- a/cognee/infrastructure/databases/vector/falkordb/FalkorDBAdapter.py +++ b/cognee/infrastructure/databases/vector/falkordb/FalkorDBAdapter.py @@ -40,7 +40,7 @@ class FalcorDBAdapter(VectorDBInterface): async def create_data_points(self, collection_name: str, data_points: List[DataPoint]): pass - async def retrieve(self, collection_name: str, data_point_id: str): + async def retrieve(self, collection_name: str, data_point_ids: list[str]): pass async def search( @@ -51,4 +51,7 @@ class FalcorDBAdapter(VectorDBInterface): limit: int = 10, with_vector: bool = False, ): - pass \ No newline at end of file + pass + + async def delete_data_points(self, collection_name: str, data_point_ids: list[str]): + pass diff --git a/cognee/infrastructure/databases/vector/lancedb/LanceDBAdapter.py b/cognee/infrastructure/databases/vector/lancedb/LanceDBAdapter.py index 77be4a154..9381639f6 100644 --- a/cognee/infrastructure/databases/vector/lancedb/LanceDBAdapter.py +++ b/cognee/infrastructure/databases/vector/lancedb/LanceDBAdapter.py @@ -33,7 +33,7 @@ class LanceDBAdapter(VectorDBInterface): async def embed_data(self, data: list[str]) -> list[list[float]]: return await self.embedding_engine.embed_text(data) - async def collection_exists(self, collection_name: str) -> bool: + async def has_collection(self, collection_name: str) -> bool: connection = await self.get_connection() collection_names = await connection.table_names() return collection_name in collection_names @@ -47,7 +47,7 @@ class LanceDBAdapter(VectorDBInterface): vector: Vector(vector_size) payload: payload_schema - if not await self.collection_exists(collection_name): + if not await self.has_collection(collection_name): connection = await self.get_connection() return await connection.create_table( name = collection_name, @@ -58,7 +58,7 @@ class LanceDBAdapter(VectorDBInterface): async def create_data_points(self, collection_name: str, data_points: List[DataPoint]): connection = await self.get_connection() - if not await self.collection_exists(collection_name): + if not await self.has_collection(collection_name): await self.create_collection( collection_name, payload_schema = type(data_points[0].payload), @@ -89,17 +89,20 @@ class LanceDBAdapter(VectorDBInterface): await collection.add(lance_data_points) - async def retrieve(self, collection_name: str, data_point_id: str): + async def retrieve(self, collection_name: str, data_point_ids: list[str]): connection = await self.get_connection() collection = await connection.open_table(collection_name) - results = await collection.query().where(f"id = '{data_point_id}'").to_pandas() - result = results.to_dict("index")[0] - return ScoredResult( + if len(data_point_ids) == 1: + results = await collection.query().where(f"id = '{data_point_ids[0]}'").to_pandas() + else: + results = await collection.query().where(f"id IN {tuple(data_point_ids)}").to_pandas() + + return [ScoredResult( id = result["id"], payload = result["payload"], score = 1, - ) + ) for result in results.to_dict("index").values()] async def search( self, @@ -122,8 +125,8 @@ class LanceDBAdapter(VectorDBInterface): return [ScoredResult( id = str(result["id"]), - score = float(result["_distance"]), payload = result["payload"], + score = float(result["_distance"]), ) for result in results.to_dict("index").values()] async def batch_search( @@ -144,6 +147,12 @@ class LanceDBAdapter(VectorDBInterface): ) for query_vector in query_vectors] ) + async def delete_data_points(self, collection_name: str, data_point_ids: list[str]): + connection = await self.get_connection() + collection = await connection.open_table(collection_name) + results = await collection.delete(f"id IN {tuple(data_point_ids)}") + return results + async def prune(self): # Clean up the database if it was set up as temporary if self.url.startswith("/"): diff --git a/cognee/infrastructure/databases/vector/qdrant/QDrantAdapter.py b/cognee/infrastructure/databases/vector/qdrant/QDrantAdapter.py index 70fd67dda..d2c02a53b 100644 --- a/cognee/infrastructure/databases/vector/qdrant/QDrantAdapter.py +++ b/cognee/infrastructure/databases/vector/qdrant/QDrantAdapter.py @@ -59,7 +59,7 @@ class QDrantAdapter(VectorDBInterface): async def embed_data(self, data: List[str]) -> List[float]: return await self.embedding_engine.embed_text(data) - async def collection_exists(self, collection_name: str) -> bool: + async def has_collection(self, collection_name: str) -> bool: client = self.get_qdrant_client() result = await client.collection_exists(collection_name) await client.close() @@ -111,11 +111,11 @@ class QDrantAdapter(VectorDBInterface): return result - async def retrieve(self, collection_name: str, data_point_id: str): + async def retrieve(self, collection_name: str, data_point_ids: list[str]): client = self.get_qdrant_client() - results = await client.retrieve(collection_name, [data_point_id], with_payload = True) + results = await client.retrieve(collection_name, data_point_ids, with_payload = True) await client.close() - return results[0] if len(results) > 0 else None + return results async def search( self, @@ -185,6 +185,11 @@ class QDrantAdapter(VectorDBInterface): return [filter(lambda result: result.score > 0.9, result_group) for result_group in results] + async def delete_data_points(self, collection_name: str, data_point_ids: list[str]): + client = self.get_qdrant_client() + results = await client.delete(collection_name, data_point_ids) + return results + async def prune(self): client = self.get_qdrant_client() diff --git a/cognee/infrastructure/databases/vector/vector_db_interface.py b/cognee/infrastructure/databases/vector/vector_db_interface.py index 3960d9269..10e268f1b 100644 --- a/cognee/infrastructure/databases/vector/vector_db_interface.py +++ b/cognee/infrastructure/databases/vector/vector_db_interface.py @@ -6,7 +6,7 @@ from .models.PayloadSchema import PayloadSchema class VectorDBInterface(Protocol): """ Collections """ @abstractmethod - async def collection_exists(self, collection_name: str) -> bool: + async def has_collection(self, collection_name: str) -> bool: raise NotImplementedError @abstractmethod @@ -28,7 +28,7 @@ class VectorDBInterface(Protocol): async def retrieve( self, collection_name: str, - data_point_id: str + data_point_ids: list[str] ): raise NotImplementedError """ Search """ @@ -51,3 +51,13 @@ class VectorDBInterface(Protocol): limit: int, with_vectors: bool = False ): raise NotImplementedError + + @abstractmethod + async def delete_data_points( + self, + collection_name: str, + data_point_ids: list[str] + ): raise NotImplementedError + + @abstractmethod + async def prune(self): raise NotImplementedError diff --git a/cognee/infrastructure/databases/vector/weaviate_db/WeaviateAdapter.py b/cognee/infrastructure/databases/vector/weaviate_db/WeaviateAdapter.py index 2f8417644..9a3ed9dd0 100644 --- a/cognee/infrastructure/databases/vector/weaviate_db/WeaviateAdapter.py +++ b/cognee/infrastructure/databases/vector/weaviate_db/WeaviateAdapter.py @@ -1,5 +1,4 @@ import asyncio -from uuid import UUID from typing import List, Optional from ..vector_db_interface import VectorDBInterface from ..models.DataPoint import DataPoint @@ -31,7 +30,7 @@ class WeaviateAdapter(VectorDBInterface): async def embed_data(self, data: List[str]) -> List[float]: return await self.embedding_engine.embed_text(data) - async def collection_exists(self, collection_name: str) -> bool: + async def has_collection(self, collection_name: str) -> bool: future = asyncio.Future() future.set_result(self.client.collections.exists(collection_name)) @@ -72,25 +71,41 @@ class WeaviateAdapter(VectorDBInterface): list(map(lambda data_point: data_point.get_embeddable_data(), data_points))) def convert_to_weaviate_data_points(data_point: DataPoint): + vector = data_vectors[data_points.index(data_point)] return DataObject( uuid = data_point.id, properties = data_point.payload.dict(), - vector = data_vectors[data_points.index(data_point)] + vector = vector ) + objects = list(map(convert_to_weaviate_data_points, data_points)) - return self.get_collection(collection_name).data.insert_many(objects) + collection = self.get_collection(collection_name) - async def retrieve(self, collection_name: str, data_point_id: str): + with collection.batch.dynamic() as batch: + for data_row in objects: + batch.add_object( + properties = data_row.properties, + vector = data_row.vector + ) + + return + # return self.get_collection(collection_name).data.insert_many(objects) + + async def retrieve(self, collection_name: str, data_point_ids: list[str]): + from weaviate.classes.query import Filter future = asyncio.Future() - data_point = self.get_collection(collection_name).query.fetch_object_by_id(UUID(data_point_id)) + data_points = self.get_collection(collection_name).query.fetch_objects( + filters = Filter.by_id().contains_any(data_point_ids) + ) - data_point.payload = data_point.properties - del data_point.properties + for data_point in data_points: + data_point.payload = data_point.properties + del data_point.properties - future.set_result(data_point) + future.set_result(data_points) return await future @@ -131,6 +146,17 @@ class WeaviateAdapter(VectorDBInterface): return self.search(collection_name, query_vector=query_vector, limit=limit, with_vector=with_vectors) return [await query_search(query_vector) for query_vector in await self.embed_data(query_texts)] + + async def delete_data_points(self, collection_name: str, data_point_ids: list[str]): + from weaviate.classes.query import Filter + future = asyncio.Future() + + result = self.get_collection(collection_name).data.delete_many( + filters = Filter.by_id().contains_any(data_point_ids) + ) + future.set_result(result) + + return await future async def prune(self): self.client.collections.delete_all() diff --git a/cognee/infrastructure/files/storage/LocalStorage.py b/cognee/infrastructure/files/storage/LocalStorage.py index 8a6b5fcd7..4db17c91b 100644 --- a/cognee/infrastructure/files/storage/LocalStorage.py +++ b/cognee/infrastructure/files/storage/LocalStorage.py @@ -32,13 +32,19 @@ class LocalStorage(Storage): f.seek(0) return f.read() + @staticmethod + def file_exists(file_path: str): + return os.path.exists(file_path) + @staticmethod def ensure_directory_exists(file_path: str): if not os.path.exists(file_path): os.makedirs(file_path, exist_ok = True) - def remove(self, file_path: str): - os.remove(self.storage_path + "/" + file_path) + @staticmethod + def remove(file_path: str): + if os.path.exists(file_path): + os.remove(file_path) @staticmethod def copy_file(source_file_path: str, destination_file_path: str): diff --git a/cognee/infrastructure/files/storage/StorageManager.py b/cognee/infrastructure/files/storage/StorageManager.py index 85a766d23..1db2d5d31 100644 --- a/cognee/infrastructure/files/storage/StorageManager.py +++ b/cognee/infrastructure/files/storage/StorageManager.py @@ -7,7 +7,8 @@ class Storage(Protocol): def retrieve(self, file_path: str): pass - def remove(self, file_path: str): + @staticmethod + def remove(file_path: str): pass class StorageManager(): diff --git a/cognee/infrastructure/files/utils/get_file_metadata.py b/cognee/infrastructure/files/utils/get_file_metadata.py index 302d00c18..4aea9560e 100644 --- a/cognee/infrastructure/files/utils/get_file_metadata.py +++ b/cognee/infrastructure/files/utils/get_file_metadata.py @@ -1,6 +1,4 @@ from typing import BinaryIO, TypedDict -from cognee.infrastructure.data.utils.extract_keywords import extract_keywords -from .extract_text_from_file import extract_text_from_file from .guess_file_type import guess_file_type @@ -8,24 +6,12 @@ class FileMetadata(TypedDict): name: str mime_type: str extension: str - keywords: list[str] def get_file_metadata(file: BinaryIO) -> FileMetadata: """Get metadata from a file""" file.seek(0) file_type = guess_file_type(file) - file.seek(0) - file_text = extract_text_from_file(file, file_type) - - import uuid - - try: - keywords = extract_keywords(file_text) - except: - keywords = ["no keywords detected" + str(uuid.uuid4())] - - file_path = file.name file_name = file_path.split("/")[-1].split(".")[0] if file_path else None @@ -34,5 +20,4 @@ def get_file_metadata(file: BinaryIO) -> FileMetadata: file_path = file_path, mime_type = file_type.mime, extension = file_type.extension, - keywords = keywords ) diff --git a/cognee/infrastructure/llm/anthropic/adapter.py b/cognee/infrastructure/llm/anthropic/adapter.py index 6ba43d699..8df59e3e5 100644 --- a/cognee/infrastructure/llm/anthropic/adapter.py +++ b/cognee/infrastructure/llm/anthropic/adapter.py @@ -19,7 +19,6 @@ class AnthropicAdapter(LLMInterface): ) self.model = model - @retry(stop = stop_after_attempt(5)) async def acreate_structured_output( self, text_input: str, @@ -31,7 +30,7 @@ class AnthropicAdapter(LLMInterface): return await self.aclient( model = self.model, max_tokens = 4096, - max_retries = 0, + max_retries = 5, messages = [{ "role": "user", "content": f"""Use the given format to extract information diff --git a/cognee/infrastructure/llm/config.py b/cognee/infrastructure/llm/config.py index 5b43aba96..a2977babd 100644 --- a/cognee/infrastructure/llm/config.py +++ b/cognee/infrastructure/llm/config.py @@ -9,6 +9,7 @@ class LLMConfig(BaseSettings): llm_api_key: Optional[str] = None llm_temperature: float = 0.0 llm_streaming: bool = False + transcription_model: str = "whisper-1" model_config = SettingsConfigDict(env_file = ".env", extra = "allow") @@ -18,6 +19,9 @@ class LLMConfig(BaseSettings): "model": self.llm_model, "endpoint": self.llm_endpoint, "apiKey": self.llm_api_key, + "temperature": self.llm_temperature, + "streaming": self.llm_stream, + "transcriptionModel": self.transcription_model } @lru_cache diff --git a/cognee/infrastructure/llm/get_llm_client.py b/cognee/infrastructure/llm/get_llm_client.py index c7481be01..16ff5b320 100644 --- a/cognee/infrastructure/llm/get_llm_client.py +++ b/cognee/infrastructure/llm/get_llm_client.py @@ -20,7 +20,7 @@ def get_llm_client(): raise ValueError("LLM API key is not set.") from .openai.adapter import OpenAIAdapter - return OpenAIAdapter(llm_config.llm_api_key, llm_config.llm_model, llm_config.llm_streaming) + return OpenAIAdapter(api_key=llm_config.llm_api_key, model=llm_config.llm_model, transcription_model=llm_config.transcription_model, streaming=llm_config.llm_streaming) elif provider == LLMProvider.OLLAMA: if llm_config.llm_api_key is None: raise ValueError("LLM API key is not set.") diff --git a/cognee/infrastructure/llm/openai/adapter.py b/cognee/infrastructure/llm/openai/adapter.py index 2e9a14492..6cac81959 100644 --- a/cognee/infrastructure/llm/openai/adapter.py +++ b/cognee/infrastructure/llm/openai/adapter.py @@ -1,5 +1,10 @@ import asyncio +import base64 +import os +from pathlib import Path from typing import List, Type + +import aiofiles import openai import instructor from pydantic import BaseModel @@ -9,6 +14,8 @@ from cognee.base_config import get_base_config from cognee.infrastructure.llm.llm_interface import LLMInterface from cognee.infrastructure.llm.prompts import read_query_prompt from cognee.shared.data_models import MonitoringTool +import logging +logging.basicConfig(level=logging.DEBUG) class OpenAIAdapter(LLMInterface): name = "OpenAI" @@ -16,20 +23,22 @@ class OpenAIAdapter(LLMInterface): api_key: str """Adapter for OpenAI's GPT-3, GPT=4 API""" - def __init__(self, api_key: str, model: str, streaming: bool = False): + def __init__(self, api_key: str, model: str, transcription_model:str, streaming: bool = False): base_config = get_base_config() - if base_config.monitoring_tool == MonitoringTool.LANGFUSE: - from langfuse.openai import AsyncOpenAI, OpenAI - elif base_config.monitoring_tool == MonitoringTool.LANGSMITH: - from langsmith import wrappers - from openai import AsyncOpenAI - AsyncOpenAI = wrappers.wrap_openai(AsyncOpenAI()) - else: - from openai import AsyncOpenAI, OpenAI + # if base_config.monitoring_tool == MonitoringTool.LANGFUSE: + # from langfuse.openai import AsyncOpenAI, OpenAI + # elif base_config.monitoring_tool == MonitoringTool.LANGSMITH: + # from langsmith import wrappers + # from openai import AsyncOpenAI + # AsyncOpenAI = wrappers.wrap_openai(AsyncOpenAI()) + # else: + from openai import AsyncOpenAI, OpenAI self.aclient = instructor.from_openai(AsyncOpenAI(api_key = api_key)) self.client = instructor.from_openai(OpenAI(api_key = api_key)) + self.base_openai_client = OpenAI(api_key = api_key) + self.transcription_model = "whisper-1" self.model = model self.api_key = api_key self.streaming = streaming @@ -120,6 +129,49 @@ class OpenAIAdapter(LLMInterface): response_model = response_model, ) + @retry(stop = stop_after_attempt(5)) + def create_transcript(self, input): + """Generate a audio transcript from a user query.""" + + if not os.path.isfile(input): + raise FileNotFoundError(f"The file {input} does not exist.") + + with open(input, 'rb') as audio_file: + audio_data = audio_file.read() + + + + transcription = self.base_openai_client.audio.transcriptions.create( + model=self.transcription_model , + file=Path(input), + ) + + return transcription + + + @retry(stop = stop_after_attempt(5)) + def transcribe_image(self, input) -> BaseModel: + with open(input, "rb") as image_file: + encoded_image = base64.b64encode(image_file.read()).decode('utf-8') + + return self.base_openai_client.chat.completions.create( + model=self.model, + messages=[ + { + "role": "user", + "content": [ + {"type": "text", "text": "What’s in this image?"}, + { + "type": "image_url", + "image_url": { + "url": f"data:image/jpeg;base64,{encoded_image}", + }, + }, + ], + } + ], + max_tokens=300, + ) def show_prompt(self, text_input: str, system_prompt: str) -> str: """Format and display the prompt for a user query.""" if not text_input: diff --git a/cognee/infrastructure/llm/prompts/categorize_summary.txt b/cognee/infrastructure/llm/prompts/categorize_summary.txt index d5e77da36..4740111ff 100644 --- a/cognee/infrastructure/llm/prompts/categorize_summary.txt +++ b/cognee/infrastructure/llm/prompts/categorize_summary.txt @@ -1,2 +1,2 @@ -Chose the summary that is the most relevant to the query`{{ query }}` -Here are the summaries:`{{ summaries }}` \ No newline at end of file +Chose the summaries that are relevant to the following query: `{{ query }}` +Here are the all summaries: `{{ summaries }}` diff --git a/cognee/infrastructure/llm/prompts/generate_graph_prompt.txt b/cognee/infrastructure/llm/prompts/generate_graph_prompt.txt index dd4b91365..a1113bee6 100644 --- a/cognee/infrastructure/llm/prompts/generate_graph_prompt.txt +++ b/cognee/infrastructure/llm/prompts/generate_graph_prompt.txt @@ -1,36 +1,26 @@ -You are a top-tier algorithm -designed for extracting information in structured formats to build a knowledge graph. -- **Nodes** represent entities and concepts. They're akin to Wikipedia nodes. -- **Edges** represent relationships between concepts. They're akin to Wikipedia links. -- The aim is to achieve simplicity and clarity in the -knowledge graph, making it accessible for a vast audience. -YOU ARE ONLY EXTRACTING DATA FOR COGNITIVE LAYER `{{ layer }}` -## 1. Labeling Nodes -- **Consistency**: Ensure you use basic or elementary types for node labels. - - For example, when you identify an entity representing a person, - always label it as **"Person"**. - Avoid using more specific terms like "mathematician" or "scientist". - - Include event, entity, time, or action nodes to the category. - - Classify the memory type as episodic or semantic. -- **Node IDs**: Never utilize integers as node IDs. - Node IDs should be names or human-readable identifiers found in the text. -## 2. Handling Numerical Data and Dates -- Numerical data, like age or other related information, -should be incorporated as attributes or properties of the respective nodes. -- **No Separate Nodes for Dates/Numbers**: -Do not create separate nodes for dates or numerical values. - Always attach them as attributes or properties of nodes. -- **Property Format**: Properties must be in a key-value format. -- **Quotation Marks**: Never use escaped single or double quotes within property values. -- **Naming Convention**: Use snake_case for relationship names, e.g., `acted_in`. -## 3. Coreference Resolution -- **Maintain Entity Consistency**: -When extracting entities, it's vital to ensure consistency. -If an entity, such as "John Doe", is mentioned multiple times -in the text but is referred to by different names or pronouns (e.g., "Joe", "he"), -always use the most complete identifier for that entity throughout the knowledge graph. - In this example, use "John Doe" as the entity ID. -Remember, the knowledge graph should be coherent and easily understandable, - so maintaining consistency in entity references is crucial. -## 4. Strict Compliance -Adhere to the rules strictly. Non-compliance will result in termination""" \ No newline at end of file +You are a top-tier algorithm designed for extracting information in structured formats to build a knowledge graph. +**Nodes** represent entities and concepts. They're akin to Wikipedia nodes. +**Edges** represent relationships between concepts. They're akin to Wikipedia links. + +The aim is to achieve simplicity and clarity in the knowledge graph, making it accessible for a vast audience. +# 1. Labeling Nodes +**Consistency**: Ensure you use basic or elementary types for node labels. + - For example, when you identify an entity representing a person, always label it as **"Person"**. + - Avoid using more specific terms like "Mathematician" or "Scientist". + - Don't use too generic terms like "Entity". +**Node IDs**: Never utilize integers as node IDs. + - Node IDs should be names or human-readable identifiers found in the text. +# 2. Handling Numerical Data and Dates + - For example, when you identify an entity representing a date, always label it as **"Date"**. + - Extract the date in the format "YYYY-MM-DD" + - If not possible to extract the whole date, extract month or year, or both if available. + - **Property Format**: Properties must be in a key-value format. + - **Quotation Marks**: Never use escaped single or double quotes within property values. + - **Naming Convention**: Use snake_case for relationship names, e.g., `acted_in`. +# 3. Coreference Resolution + - **Maintain Entity Consistency**: When extracting entities, it's vital to ensure consistency. + If an entity, such as "John Doe", is mentioned multiple times in the text but is referred to by different names or pronouns (e.g., "Joe", "he"), + always use the most complete identifier for that entity throughout the knowledge graph. In this example, use "John Doe" as the Persons ID. +Remember, the knowledge graph should be coherent and easily understandable, so maintaining consistency in entity references is crucial. +# 4. Strict Compliance +Adhere to the rules strictly. Non-compliance will result in termination""" diff --git a/cognee/infrastructure/llm/prompts/summarize_content.txt b/cognee/infrastructure/llm/prompts/summarize_content.txt index 7c229eab6..3bd06662d 100644 --- a/cognee/infrastructure/llm/prompts/summarize_content.txt +++ b/cognee/infrastructure/llm/prompts/summarize_content.txt @@ -1 +1,3 @@ -You are a summarization engine and you should sumamarize content. Be brief and concise \ No newline at end of file +You are a top-tier summarization engine. Your task is to summarize text and make it versatile. +Be brief and concise, but keep the important information and the subject. +Use synonim words where possible in order to change the wording but keep the meaning. diff --git a/cognee/modules/classification/__init__.py b/cognee/modules/classification/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/cognee/modules/classification/classify_text_chunks.py b/cognee/modules/classification/classify_text_chunks.py new file mode 100644 index 000000000..97dd90e56 --- /dev/null +++ b/cognee/modules/classification/classify_text_chunks.py @@ -0,0 +1,152 @@ + +import asyncio +from uuid import uuid5, NAMESPACE_OID +from typing import Type +from pydantic import BaseModel +from cognee.infrastructure.databases.graph import get_graph_engine +from cognee.infrastructure.databases.vector import get_vector_engine, DataPoint +from cognee.modules.data.processing.chunk_types.DocumentChunk import DocumentChunk +from ..data.extraction.extract_categories import extract_categories + +async def classify_text_chunks(data_chunks: list[DocumentChunk], classification_model: Type[BaseModel]): + if len(data_chunks) == 0: + return data_chunks + + chunk_classifications = await asyncio.gather( + *[extract_categories(chunk.text, classification_model) for chunk in data_chunks], + ) + + classification_data_points = [] + + for chunk_index, chunk in enumerate(data_chunks): + chunk_classification = chunk_classifications[chunk_index] + classification_data_points.append(uuid5(NAMESPACE_OID, chunk_classification.label.type)) + classification_data_points.append(uuid5(NAMESPACE_OID, chunk_classification.label.type)) + + for classification_subclass in chunk_classification.label.subclass: + classification_data_points.append(uuid5(NAMESPACE_OID, classification_subclass.value)) + + vector_engine = get_vector_engine() + + class Keyword(BaseModel): + id: str + text: str + chunk_id: str + document_id: str + + collection_name = "classification" + + if await vector_engine.has_collection(collection_name): + existing_data_points = await vector_engine.retrieve( + collection_name, + list(set(classification_data_points)), + ) if len(classification_data_points) > 0 else [] + + existing_points_map = {point.id: True for point in existing_data_points} + else: + existing_points_map = {} + await vector_engine.create_collection(collection_name, payload_schema = Keyword) + + data_points = [] + nodes = [] + edges = [] + + for (chunk_index, data_chunk) in enumerate(data_chunks): + chunk_classification = chunk_classifications[chunk_index] + classification_type_label = chunk_classification.label.type + classification_type_id = uuid5(NAMESPACE_OID, classification_type_label) + + if classification_type_id not in existing_points_map: + data_points.append( + DataPoint[Keyword]( + id = str(classification_type_id), + payload = Keyword.parse_obj({ + "id": str(classification_type_id), + "text": classification_type_label, + "chunk_id": str(data_chunk.chunk_id), + "document_id": str(data_chunk.document_id), + }), + embed_field = "text", + ) + ) + + nodes.append(( + str(classification_type_id), + dict( + id = str(classification_type_id), + name = classification_type_label, + type = classification_type_label, + ) + )) + existing_points_map[classification_type_id] = True + + edges.append(( + str(data_chunk.chunk_id), + str(classification_type_id), + "is_media_type", + dict( + relationship_name = "is_media_type", + source_node_id = str(data_chunk.chunk_id), + target_node_id = str(classification_type_id), + ), + )) + + for classification_subclass in chunk_classification.label.subclass: + classification_subtype_label = classification_subclass.value + classification_subtype_id = uuid5(NAMESPACE_OID, classification_subtype_label) + + if classification_subtype_id not in existing_points_map: + data_points.append( + DataPoint[Keyword]( + id = str(classification_subtype_id), + payload = Keyword.parse_obj({ + "id": str(classification_subtype_id), + "text": classification_subtype_label, + "chunk_id": str(data_chunk.chunk_id), + "document_id": str(data_chunk.document_id), + }), + embed_field = "text", + ) + ) + + nodes.append(( + str(classification_subtype_id), + dict( + id = str(classification_subtype_id), + name = classification_subtype_label, + type = classification_subtype_label, + ) + )) + edges.append(( + str(classification_type_id), + str(classification_subtype_id), + "contains", + dict( + relationship_name = "contains", + source_node_id = str(classification_type_id), + target_node_id = str(classification_subtype_id), + ), + )) + + existing_points_map[classification_subtype_id] = True + + edges.append(( + str(data_chunk.chunk_id), + str(classification_subtype_id), + "is_classified_as", + dict( + relationship_name = "is_classified_as", + source_node_id = str(data_chunk.chunk_id), + target_node_id = str(classification_subtype_id), + ), + )) + + if len(nodes) > 0 or len(edges) > 0: + await vector_engine.create_data_points(collection_name, data_points) + + graph_engine = await get_graph_engine() + + await graph_engine.add_nodes(nodes) + await graph_engine.add_edges(edges) + + return data_chunks diff --git a/cognee/modules/cognify/graph/add_node_connections.py b/cognee/modules/cognify/graph/add_node_connections.py index 33cd498ad..5ec38ec1a 100644 --- a/cognee/modules/cognify/graph/add_node_connections.py +++ b/cognee/modules/cognify/graph/add_node_connections.py @@ -1,6 +1,6 @@ import uuid -from cognee.infrastructure.databases.graph.get_graph_client import get_graph_client +from cognee.infrastructure.databases.graph.get_graph_engine import get_graph_engine from cognee.shared.data_models import GraphDBType from cognee.infrastructure.databases.graph.config import get_graph_config @@ -92,7 +92,7 @@ def graph_ready_output(results): if __name__ == "__main__": async def main(): - graph_client = await get_graph_client() + graph_client = await get_graph_engine() graph = graph_client.graph # for nodes, attr in graph.nodes(data=True): diff --git a/cognee/modules/cognify/graph/save_chunk_relationships.py b/cognee/modules/cognify/graph/save_chunk_relationships.py new file mode 100644 index 000000000..e69de29bb diff --git a/cognee/modules/cognify/graph/save_document_node.py b/cognee/modules/cognify/graph/save_document_node.py new file mode 100644 index 000000000..a772afbd7 --- /dev/null +++ b/cognee/modules/cognify/graph/save_document_node.py @@ -0,0 +1,18 @@ +from uuid import UUID +from cognee.shared.data_models import Document +from cognee.infrastructure.databases.graph import get_graph_engine + +async def save_document_node(document: Document, parent_node_id: UUID = None): + graph_engine = get_graph_engine() + + await graph_engine.add_node(document.id, document.model_dump()) + + if parent_node_id: + await graph_engine.add_edge( + parent_node_id, + document.id, + "has_document", + dict(relationship_name = "has_document"), + ) + + return document diff --git a/cognee/modules/cognify/vector/__init__.py b/cognee/modules/cognify/vector/__init__.py new file mode 100644 index 000000000..4edc54272 --- /dev/null +++ b/cognee/modules/cognify/vector/__init__.py @@ -0,0 +1 @@ +from .save_data_chunks import save_data_chunks diff --git a/cognee/modules/cognify/vector/save_data_chunks.py b/cognee/modules/cognify/vector/save_data_chunks.py new file mode 100644 index 000000000..943ba336c --- /dev/null +++ b/cognee/modules/cognify/vector/save_data_chunks.py @@ -0,0 +1,97 @@ +from cognee.infrastructure.databases.vector import DataPoint, get_vector_engine +from cognee.infrastructure.databases.graph import get_graph_engine +from cognee.modules.data.processing.chunk_types.DocumentChunk import DocumentChunk + +async def save_data_chunks(data_chunks: list[DocumentChunk], collection_name: str): + if len(data_chunks) == 0: + return data_chunks + + vector_engine = get_vector_engine() + graph_engine = await get_graph_engine() + + # Remove and unlink existing chunks + if await vector_engine.has_collection(collection_name): + existing_chunks = [DocumentChunk.parse_obj(chunk.payload) for chunk in (await vector_engine.retrieve( + collection_name, + [str(chunk.chunk_id) for chunk in data_chunks], + ))] + + if len(existing_chunks) > 0: + await vector_engine.delete_data_points(collection_name, [str(chunk.chunk_id) for chunk in existing_chunks]) + + await graph_engine.remove_connection_to_successors_of([chunk.chunk_id for chunk in existing_chunks], "next_chunk") + await graph_engine.remove_connection_to_predecessors_of([chunk.chunk_id for chunk in existing_chunks], "has_chunk") + else: + await vector_engine.create_collection(collection_name, payload_schema = DocumentChunk) + + # Add to vector storage + await vector_engine.create_data_points( + collection_name, + [ + DataPoint[DocumentChunk]( + id = str(chunk.chunk_id), + payload = chunk, + embed_field = "text", + ) for chunk in data_chunks + ], + ) + + # Add to graph storage + chunk_nodes = [] + chunk_edges = [] + + for chunk in data_chunks: + chunk_nodes.append(( + str(chunk.chunk_id), + dict( + id = str(chunk.chunk_id), + chunk_id = str(chunk.chunk_id), + document_id = str(chunk.document_id), + word_count = chunk.word_count, + chunk_index = chunk.chunk_index, + cut_type = chunk.cut_type, + pages = chunk.pages, + ) + )) + + chunk_edges.append(( + str(chunk.document_id), + str(chunk.chunk_id), + "has_chunk", + dict( + relationship_name = "has_chunk", + source_node_id = str(chunk.document_id), + target_node_id = str(chunk.chunk_id), + ), + )) + + previous_chunk_id = get_previous_chunk_id(data_chunks, chunk) + + if previous_chunk_id is not None: + chunk_edges.append(( + str(previous_chunk_id), + str(chunk.chunk_id), + "next_chunk", + dict( + relationship_name = "next_chunk", + source_node_id = str(previous_chunk_id), + target_node_id = str(chunk.chunk_id), + ), + )) + + await graph_engine.add_nodes(chunk_nodes) + await graph_engine.add_edges(chunk_edges) + + return data_chunks + + +def get_previous_chunk_id(document_chunks: list[DocumentChunk], current_chunk: DocumentChunk) -> DocumentChunk: + if current_chunk.chunk_index == 0: + return current_chunk.document_id + + for chunk in document_chunks: + if str(chunk.document_id) == str(current_chunk.document_id) \ + and chunk.chunk_index == current_chunk.chunk_index - 1: + return chunk.chunk_id + + return None diff --git a/cognee/modules/data/chunking/__init__.py b/cognee/modules/data/chunking/__init__.py new file mode 100644 index 000000000..a974e86b0 --- /dev/null +++ b/cognee/modules/data/chunking/__init__.py @@ -0,0 +1,3 @@ +from .chunk_by_word import chunk_by_word +from .chunk_by_sentence import chunk_by_sentence +from .chunk_by_paragraph import chunk_by_paragraph diff --git a/cognee/modules/data/chunking/__tests__/chunk_by_paragraph.test.py b/cognee/modules/data/chunking/__tests__/chunk_by_paragraph.test.py new file mode 100644 index 000000000..91b314f92 --- /dev/null +++ b/cognee/modules/data/chunking/__tests__/chunk_by_paragraph.test.py @@ -0,0 +1,53 @@ +from cognee.modules.data.chunking import chunk_by_paragraph + +if __name__ == "__main__": + def test_chunking_on_whole_text(): + test_text = """This is example text. It contains multiple sentences. + This is a second paragraph. First two paragraphs are whole. + Third paragraph is a bit longer and is finished with a dot.""" + + chunks = [] + + for chunk_data in chunk_by_paragraph(test_text, 12, batch_paragraphs = False): + chunks.append(chunk_data) + + assert len(chunks) == 3 + + assert chunks[0]["text"] == "This is example text. It contains multiple sentences." + assert chunks[0]["word_count"] == 8 + assert chunks[0]["cut_type"] == "paragraph_end" + + assert chunks[1]["text"] == "This is a second paragraph. First two paragraphs are whole." + assert chunks[1]["word_count"] == 10 + assert chunks[1]["cut_type"] == "paragraph_end" + + assert chunks[2]["text"] == "Third paragraph is a bit longer and is finished with a dot." + assert chunks[2]["word_count"] == 12 + assert chunks[2]["cut_type"] == "sentence_end" + + def test_chunking_on_cut_text(): + test_text = """This is example text. It contains multiple sentences. + This is a second paragraph. First two paragraphs are whole. + Third paragraph is cut and is missing the dot at the end""" + + chunks = [] + + for chunk_data in chunk_by_paragraph(test_text, 12, batch_paragraphs = False): + chunks.append(chunk_data) + + assert len(chunks) == 3 + + assert chunks[0]["text"] == "This is example text. It contains multiple sentences." + assert chunks[0]["word_count"] == 8 + assert chunks[0]["cut_type"] == "paragraph_end" + + assert chunks[1]["text"] == "This is a second paragraph. First two paragraphs are whole." + assert chunks[1]["word_count"] == 10 + assert chunks[1]["cut_type"] == "paragraph_end" + + assert chunks[2]["text"] == "Third paragraph is cut and is missing the dot at the end" + assert chunks[2]["word_count"] == 12 + assert chunks[2]["cut_type"] == "sentence_cut" + + test_chunking_on_whole_text() + test_chunking_on_cut_text() diff --git a/cognee/modules/data/chunking/chunk_by_paragraph.py b/cognee/modules/data/chunking/chunk_by_paragraph.py new file mode 100644 index 000000000..eae5f812f --- /dev/null +++ b/cognee/modules/data/chunking/chunk_by_paragraph.py @@ -0,0 +1,69 @@ +from uuid import uuid5, NAMESPACE_OID +from .chunk_by_sentence import chunk_by_sentence + +def chunk_by_paragraph(data: str, paragraph_length: int = 1024, batch_paragraphs = True): + paragraph = "" + last_cut_type = None + last_paragraph_id = None + paragraph_word_count = 0 + paragraph_chunk_index = 0 + + for (paragraph_id, __, sentence, word_count, end_type) in chunk_by_sentence(data): + if paragraph_word_count > 0 and paragraph_word_count + word_count > paragraph_length: + if batch_paragraphs is True: + chunk_id = uuid5(NAMESPACE_OID, paragraph) + yield dict( + text = paragraph.strip(), + word_count = paragraph_word_count, + id = chunk_id, # When batching paragraphs, the paragraph_id is the same as chunk_id. + # paragraph_id doens't mean anything since multiple paragraphs are merged. + chunk_id = chunk_id, + chunk_index = paragraph_chunk_index, + cut_type = last_cut_type, + ) + else: + yield dict( + text = paragraph.strip(), + word_count = paragraph_word_count, + id = last_paragraph_id, + chunk_id = uuid5(NAMESPACE_OID, paragraph), + chunk_index = paragraph_chunk_index, + cut_type = last_cut_type, + ) + + paragraph_chunk_index += 1 + paragraph_word_count = 0 + paragraph = "" + + paragraph += (" " if len(paragraph) > 0 else "") + sentence + paragraph_word_count += word_count + + if end_type == "paragraph_end" or end_type == "sentence_cut": + if batch_paragraphs is True: + paragraph += "\n\n" if end_type == "paragraph_end" else "" + else: + yield dict( + text = paragraph.strip(), + word_count = paragraph_word_count, + paragraph_id = paragraph_id, + chunk_id = uuid5(NAMESPACE_OID, paragraph), + chunk_index = paragraph_chunk_index, + cut_type = end_type, + ) + + paragraph_chunk_index = 0 + paragraph_word_count = 0 + paragraph = "" + + last_cut_type = end_type + last_paragraph_id = paragraph_id + + if len(paragraph) > 0: + yield dict( + chunk_id = uuid5(NAMESPACE_OID, paragraph), + text = paragraph, + word_count = paragraph_word_count, + paragraph_id = last_paragraph_id, + chunk_index = paragraph_chunk_index, + cut_type = last_cut_type, + ) diff --git a/cognee/modules/data/chunking/chunk_by_sentence.py b/cognee/modules/data/chunking/chunk_by_sentence.py new file mode 100644 index 000000000..5189635dd --- /dev/null +++ b/cognee/modules/data/chunking/chunk_by_sentence.py @@ -0,0 +1,28 @@ +from uuid import uuid4 +from .chunk_by_word import chunk_by_word + +def chunk_by_sentence(data: str): + sentence = "" + paragraph_id = uuid4() + chunk_index = 0 + word_count = 0 + + for (word, word_type) in chunk_by_word(data): + sentence += (" " if len(sentence) > 0 else "") + word + word_count += 1 + + if word_type == "paragraph_end" or word_type == "sentence_end": + yield (paragraph_id, chunk_index, sentence, word_count, word_type) + sentence = "" + word_count = 0 + paragraph_id = uuid4() if word_type == "paragraph_end" else paragraph_id + chunk_index = 0 if word_type == "paragraph_end" else chunk_index + 1 + + if len(sentence) > 0: + yield ( + paragraph_id, + chunk_index, + sentence, + word_count, + "sentence_cut", + ) diff --git a/cognee/modules/data/chunking/chunk_by_word.py b/cognee/modules/data/chunking/chunk_by_word.py new file mode 100644 index 000000000..644404b2d --- /dev/null +++ b/cognee/modules/data/chunking/chunk_by_word.py @@ -0,0 +1,60 @@ +import re + +def chunk_by_word(data: str): + sentence_endings = r"[.;!?…]" + paragraph_endings = r"[\n\r]" + last_processed_character = "" + + word = "" + i = 0 + + while i < len(data): + character = data[i] + + if word == "" and (re.match(paragraph_endings, character) or character == " "): + i = i + 1 + continue + + def is_real_paragraph_end(): + if re.match(sentence_endings, last_processed_character): + return True + + j = i + 1 + next_character = data[j] if j < len(data) else None + while next_character is not None and (re.match(paragraph_endings, next_character) or next_character == " "): + j += 1 + next_character = data[j] if j < len(data) else None + if next_character.isupper(): + return True + + return False + + if re.match(paragraph_endings, character): + yield (word, "paragraph_end" if is_real_paragraph_end() else "word") + word = "" + i = i + 1 + continue + + if character == " ": + yield [word, "word"] + word = "" + i = i + 1 + continue + + word += character + last_processed_character = character + + if re.match(sentence_endings, character): + # Check for ellipses. + if i + 2 <= len(data) and data[i] == "." and data[i + 1] == "." and data[i + 2] == ".": + word += ".." + i = i + 2 + + is_paragraph_end = i + 1 < len(data) and re.match(paragraph_endings, data[i + 1]) + yield (word, "paragraph_end" if is_paragraph_end else "sentence_end") + word = "" + + i += 1 + + if len(word) > 0: + yield (word, "word") diff --git a/cognee/modules/data/deletion/__init__.py b/cognee/modules/data/deletion/__init__.py index 59ee686e0..ac63645ae 100644 --- a/cognee/modules/data/deletion/__init__.py +++ b/cognee/modules/data/deletion/__init__.py @@ -1 +1,2 @@ +from .prune_data import prune_data from .prune_system import prune_system diff --git a/cognee/modules/data/deletion/prune_data.py b/cognee/modules/data/deletion/prune_data.py new file mode 100644 index 000000000..cef0c5ffa --- /dev/null +++ b/cognee/modules/data/deletion/prune_data.py @@ -0,0 +1,7 @@ +from cognee.base_config import get_base_config +from cognee.infrastructure.files.storage import LocalStorage + +async def prune_data(): + base_config = get_base_config() + data_root_directory = base_config.data_root_directory + LocalStorage.remove_all(data_root_directory) diff --git a/cognee/modules/data/deletion/prune_system.py b/cognee/modules/data/deletion/prune_system.py index a913edeec..70627bdc7 100644 --- a/cognee/modules/data/deletion/prune_system.py +++ b/cognee/modules/data/deletion/prune_system.py @@ -1,13 +1,17 @@ from cognee.infrastructure.databases.vector import get_vector_engine -from cognee.infrastructure.databases.graph.config import get_graph_config -from cognee.infrastructure.databases.graph.get_graph_client import get_graph_client +from cognee.infrastructure.databases.graph.get_graph_engine import get_graph_engine +from cognee.infrastructure.databases.relational import get_relationaldb_config -async def prune_system(graph = True, vector = True): +async def prune_system(graph = True, vector = True, metadata = False): if graph: - graph_config = get_graph_config() - graph_client = await get_graph_client() - await graph_client.delete_graph() + graph_engine = await get_graph_engine() + await graph_engine.delete_graph() if vector: vector_engine = get_vector_engine() await vector_engine.prune() + + if metadata: + db_config = get_relationaldb_config() + db_engine = db_config.database_engine + db_engine.delete_database() diff --git a/cognee/modules/data/extraction/__init__.py b/cognee/modules/data/extraction/__init__.py index e69de29bb..8bb2d8ca3 100644 --- a/cognee/modules/data/extraction/__init__.py +++ b/cognee/modules/data/extraction/__init__.py @@ -0,0 +1 @@ +from .extract_topics import extract_topics_yake, extract_topics_keybert diff --git a/cognee/modules/data/extraction/data_summary/__init__.py b/cognee/modules/data/extraction/data_summary/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/cognee/modules/data/extraction/data_summary/models/TextSummary.py b/cognee/modules/data/extraction/data_summary/models/TextSummary.py new file mode 100644 index 000000000..ed4471830 --- /dev/null +++ b/cognee/modules/data/extraction/data_summary/models/TextSummary.py @@ -0,0 +1,5 @@ +from pydantic import BaseModel + +class TextSummary(BaseModel): + text: str + chunk_id: str diff --git a/cognee/modules/data/extraction/data_summary/summarize_text_chunks.py b/cognee/modules/data/extraction/data_summary/summarize_text_chunks.py new file mode 100644 index 000000000..fa481a7d9 --- /dev/null +++ b/cognee/modules/data/extraction/data_summary/summarize_text_chunks.py @@ -0,0 +1,36 @@ + +import asyncio +from typing import Type +from pydantic import BaseModel +from cognee.infrastructure.databases.vector import get_vector_engine, DataPoint +from ...processing.chunk_types.DocumentChunk import DocumentChunk +from ...extraction.extract_summary import extract_summary +from .models.TextSummary import TextSummary + +async def summarize_text_chunks(data_chunks: list[DocumentChunk], summarization_model: Type[BaseModel], collection_name: str = "summaries"): + if len(data_chunks) == 0: + return data_chunks + + chunk_summaries = await asyncio.gather( + *[extract_summary(chunk.text, summarization_model) for chunk in data_chunks] + ) + + vector_engine = get_vector_engine() + + await vector_engine.create_collection(collection_name, payload_schema = TextSummary) + + await vector_engine.create_data_points( + collection_name, + [ + DataPoint[TextSummary]( + id = str(chunk.chunk_id), + payload = dict( + chunk_id = str(chunk.chunk_id), + text = chunk_summaries[chunk_index].summary, + ), + embed_field = "text", + ) for (chunk_index, chunk) in enumerate(data_chunks) + ], + ) + + return data_chunks diff --git a/cognee/modules/data/extraction/extract_categories.py b/cognee/modules/data/extraction/extract_categories.py index 7d4408cab..3de26e59d 100644 --- a/cognee/modules/data/extraction/extract_categories.py +++ b/cognee/modules/data/extraction/extract_categories.py @@ -11,16 +11,4 @@ async def extract_categories(content: str, response_model: Type[BaseModel]): llm_output = await llm_client.acreate_structured_output(content, system_prompt, response_model) - return process_categories(llm_output.model_dump()) - -def process_categories(llm_output) -> List[dict]: - # Extract the first subclass from the list (assuming there could be more) - data_category = llm_output["label"]["subclass"][0] if len(llm_output["label"]["subclass"]) > 0 else None - - data_type = llm_output["label"]["type"].lower() - - return [{ - "data_type": data_type, - # The data_category is the value of the Enum member (e.g., "News stories and blog posts") - "category_name": data_category.value if data_category else "Other types of text data", - }] + return llm_output diff --git a/cognee/modules/data/extraction/extract_summary.py b/cognee/modules/data/extraction/extract_summary.py index 27c2fca25..a17bf3ae6 100644 --- a/cognee/modules/data/extraction/extract_summary.py +++ b/cognee/modules/data/extraction/extract_summary.py @@ -10,4 +10,4 @@ async def extract_summary(content: str, response_model: Type[BaseModel]): llm_output = await llm_client.acreate_structured_output(content, system_prompt, response_model) - return llm_output.model_dump() + return llm_output diff --git a/cognee/modules/data/extraction/extract_topics.py b/cognee/modules/data/extraction/extract_topics.py new file mode 100644 index 000000000..a7ff248bc --- /dev/null +++ b/cognee/modules/data/extraction/extract_topics.py @@ -0,0 +1,113 @@ +import re +import nltk +from nltk.tag import pos_tag +from nltk.corpus import stopwords, wordnet +from nltk.tokenize import word_tokenize +from nltk.stem import WordNetLemmatizer + +def extract_topics_yake(texts: list[str]): + from yake import KeywordExtractor + + keyword_extractor = KeywordExtractor( + top = 3, + n = 2, + dedupLim = 0.2, + dedupFunc = "levenshtein", # "seqm" | "levenshtein" + windowsSize = 1, + ) + + for text in texts: + topics = keyword_extractor.extract_keywords(preprocess_text(text)) + yield [topic[0] for topic in topics] + +def extract_topics_keybert(texts: list[str]): + from keybert import KeyBERT + + kw_model = KeyBERT() + + for text in texts: + topics = kw_model.extract_keywords( + preprocess_text(text), + keyphrase_ngram_range = (1, 2), + top_n = 3, + # use_mmr = True, + # diversity = 0.9, + ) + yield [topic[0] for topic in topics] + +def preprocess_text(text: str): + try: + # Used for stopwords removal. + stopwords.ensure_loaded() + except LookupError: + nltk.download("stopwords", quiet = True) + stopwords.ensure_loaded() + + try: + # Used in WordNetLemmatizer. + wordnet.ensure_loaded() + except LookupError: + nltk.download("wordnet", quiet = True) + wordnet.ensure_loaded() + + try: + # Used in word_tokenize. + nltk.data.find("tokenizers/punkt") + except LookupError: + nltk.download("punkt", quiet = True) + + text = text.lower() + + # Remove punctuation + text = re.sub(r"[^\w\s-]", "", text) + + # Tokenize the text + tokens = word_tokenize(text) + + tagged_tokens = pos_tag(tokens) + tokens = [word for word, tag in tagged_tokens if tag in ["NNP", "NN", "JJ"]] + + # Remove stop words + stop_words = set(stopwords.words("english")) + tokens = [word for word in tokens if word not in stop_words] + + # Lemmatize the text + lemmatizer = WordNetLemmatizer() + tokens = [lemmatizer.lemmatize(word) for word in tokens] + + # Join tokens back to a single string + processed_text = " ".join(tokens) + + return processed_text + + +# def clean_text(text: str): +# text = re.sub(r"[ \t]{2,}|[\n\r]", " ", text.lower()) +# # text = re.sub(r"[`\"'.,;!?…]", "", text).strip() +# return text + +# def remove_stop_words(text: str): +# try: +# stopwords.ensure_loaded() +# except LookupError: +# download("stopwords") +# stopwords.ensure_loaded() + +# stop_words = set(stopwords.words("english")) +# text = text.split() +# text = [word for word in text if not word in stop_words] +# return " ".join(text) + + +if __name__ == "__main__": + import os + + file_dir = os.path.dirname(os.path.realpath(__file__)) + + with open(os.path.join(file_dir, "texts.json"), "r", encoding = "utf-8") as file: + import json + texts = json.load(file) + + for topics in extract_topics_yake(texts): + print(topics) + print("\n") diff --git a/cognee/modules/data/extraction/extract_topics_naive.py b/cognee/modules/data/extraction/extract_topics_naive.py new file mode 100644 index 000000000..a8487224f --- /dev/null +++ b/cognee/modules/data/extraction/extract_topics_naive.py @@ -0,0 +1,66 @@ +import re +from nltk.downloader import download +from nltk.stem import WordNetLemmatizer +from nltk.tokenize import sent_tokenize, word_tokenize +from nltk.corpus import stopwords, wordnet +from sklearn.feature_extraction.text import TfidfVectorizer +from sklearn.decomposition import TruncatedSVD + +def extract_topics(text: str): + sentences = sent_tokenize(text) + + try: + wordnet.ensure_loaded() + except LookupError: + download("wordnet") + wordnet.ensure_loaded() + + lemmatizer = WordNetLemmatizer() + base_notation_sentences = [lemmatizer.lemmatize(sentence) for sentence in sentences] + + tf_vectorizer = TfidfVectorizer(tokenizer = word_tokenize, token_pattern = None) + transformed_corpus = tf_vectorizer.fit_transform(base_notation_sentences) + + svd = TruncatedSVD(n_components = 10) + svd_corpus = svd.fit(transformed_corpus) + + feature_scores = dict( + zip( + tf_vectorizer.vocabulary_, + svd_corpus.components_[0] + ) + ) + + topics = sorted( + feature_scores, + # key = feature_scores.get, + key = lambda x: transformed_corpus[0, tf_vectorizer.vocabulary_[x]], + reverse = True, + )[:10] + + return topics + + +def clean_text(text: str): + text = re.sub(r"[ \t]{2,}|[\n\r]", " ", text.lower()) + return re.sub(r"[`\"'.,;!?…]", "", text).strip() + +def remove_stop_words(text: str): + try: + stopwords.ensure_loaded() + except LookupError: + download("stopwords") + stopwords.ensure_loaded() + + stop_words = set(stopwords.words("english")) + text = text.split() + text = [word for word in text if not word in stop_words] + return " ".join(text) + + +if __name__ == "__main__": + text = """Lorem Ipsum is simply dummy text of the printing and typesetting industry... Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book… It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. + Why do we use it? + It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout! The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like). + """ + print(extract_topics(remove_stop_words(clean_text(text)))) diff --git a/cognee/modules/data/extraction/knowledge_graph/add_model_class_to_graph.py b/cognee/modules/data/extraction/knowledge_graph/add_model_class_to_graph.py new file mode 100644 index 000000000..08691cbf2 --- /dev/null +++ b/cognee/modules/data/extraction/knowledge_graph/add_model_class_to_graph.py @@ -0,0 +1,70 @@ +from typing import Type, Optional, get_args, get_origin +from pydantic import BaseModel +from cognee.infrastructure.databases.graph.graph_db_interface import GraphDBInterface + +async def add_model_class_to_graph( + model_class: Type[BaseModel], + graph: GraphDBInterface, + parent: Optional[str] = None, + relationship: Optional[str] = None, +): + model_name = model_class.__name__ + + if await graph.extract_node(model_name): + return + + await graph.add_node(model_name, dict(type = "model")) + + if parent and relationship: + await graph.add_edge( + parent, + model_name, + relationship, + dict( + relationship_name = relationship, + source_node_id = parent, + target_node_id = model_name, + ), + ) + + for field_name, field in model_class.model_fields.items(): + original_types = get_args(field.annotation) + field_type = original_types[0] if len(original_types) > 0 else None + + if field_type is None: + continue + + if hasattr(field_type, "model_fields"): # Check if field type is a Pydantic model + await add_model_class_to_graph(field_type, graph, model_name, field_name) + elif get_origin(field.annotation) == list: + list_types = get_args(field_type) + for item_type in list_types: + await add_model_class_to_graph(item_type, graph, model_name, field_name) + elif isinstance(field_type, list): + item_type = get_args(field_type)[0] + if hasattr(item_type, "model_fields"): + await add_model_class_to_graph(item_type, graph, model_name, field_name) + else: + await graph.add_node(str(item_type), dict(type = "value")) + await graph.add_edge( + model_name, + str(item_type), + field_name, + dict( + relationship_name = field_name, + source_node_id = model_name, + target_node_id = str(item_type), + ), + ) + else: + await graph.add_node(str(field_type), dict(type = "value")) + await graph.add_edge( + model_name, + str(field_type), + field_name, + dict( + relationship_name = field_name, + source_node_id = model_name, + target_node_id = str(field_type), + ), + ) diff --git a/cognee/modules/data/extraction/knowledge_graph/establish_graph_topology.py b/cognee/modules/data/extraction/knowledge_graph/establish_graph_topology.py new file mode 100644 index 000000000..ce061874c --- /dev/null +++ b/cognee/modules/data/extraction/knowledge_graph/establish_graph_topology.py @@ -0,0 +1,20 @@ +from typing import Type +from pydantic import BaseModel +from cognee.shared.data_models import KnowledgeGraph +from cognee.infrastructure.databases.graph import get_graph_engine +from ...processing.chunk_types.DocumentChunk import DocumentChunk +from .add_model_class_to_graph import add_model_class_to_graph + +async def establish_graph_topology(data_chunks: list[DocumentChunk], topology_model: Type[BaseModel]): + if topology_model == KnowledgeGraph: + return data_chunks + + graph_engine = await get_graph_engine() + + await add_model_class_to_graph(topology_model, graph_engine) + + return data_chunks + + +def generate_node_id(node_id: str) -> str: + return node_id.upper().replace(" ", "_").replace("'", "") diff --git a/cognee/modules/data/extraction/knowledge_graph/expand_knowledge_graph.py b/cognee/modules/data/extraction/knowledge_graph/expand_knowledge_graph.py new file mode 100644 index 000000000..d6475512d --- /dev/null +++ b/cognee/modules/data/extraction/knowledge_graph/expand_knowledge_graph.py @@ -0,0 +1,117 @@ +import asyncio +from datetime import datetime +from typing import Type +from pydantic import BaseModel +from cognee.infrastructure.databases.graph import get_graph_engine +from ...processing.chunk_types.DocumentChunk import DocumentChunk +from .extract_knowledge_graph import extract_content_graph + +async def expand_knowledge_graph(data_chunks: list[DocumentChunk], graph_model: Type[BaseModel]): + chunk_graphs = await asyncio.gather( + *[extract_content_graph(chunk.text, graph_model) for chunk in data_chunks] + ) + + graph_engine = await get_graph_engine() + + type_ids = [generate_node_id(node.type) for chunk_graph in chunk_graphs for node in chunk_graph.nodes] + graph_type_node_ids = list(set(type_ids)) + graph_type_nodes = await graph_engine.extract_nodes(graph_type_node_ids) + existing_type_nodes_map = {node["id"]: node for node in graph_type_nodes} + + graph_nodes = [] + graph_edges = [] + + for (chunk_index, chunk) in enumerate(data_chunks): + graph = chunk_graphs[chunk_index] + if graph is None: + continue + + for node in graph.nodes: + node_id = generate_node_id(node.id) + + graph_nodes.append(( + node_id, + dict( + id = node_id, + chunk_id = str(chunk.chunk_id), + document_id = str(chunk.document_id), + name = node.name, + type = node.type.lower().capitalize(), + description = node.description, + created_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + updated_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + ) + )) + + graph_edges.append(( + str(chunk.chunk_id), + node_id, + "contains", + dict( + relationship_name = "contains", + source_node_id = str(chunk.chunk_id), + target_node_id = node_id, + ), + )) + + type_node_id = generate_node_id(node.type) + + if type_node_id not in existing_type_nodes_map: + node_name = node.type.lower().capitalize() + + type_node = dict( + id = type_node_id, + name = node_name, + type = node_name, + created_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + updated_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + ) + + graph_nodes.append((type_node_id, type_node)) + existing_type_nodes_map[type_node_id] = type_node + + graph_edges.append(( + str(chunk.chunk_id), + type_node_id, + "contains_entity_type", + dict( + relationship_name = "contains_entity_type", + source_node_id = str(chunk.chunk_id), + target_node_id = type_node_id, + ), + )) + + # Add relationship between entity type and entity itself: "Jake is Person" + graph_edges.append(( + type_node_id, + node_id, + "is_entity_type", + dict( + relationship_name = "is_entity_type", + source_node_id = type_node_id, + target_node_id = node_id, + ), + )) + + # Add relationship that came from graphs. + for edge in graph.edges: + graph_edges.append(( + generate_node_id(edge.source_node_id), + generate_node_id(edge.target_node_id), + edge.relationship_name, + dict( + relationship_name = edge.relationship_name, + source_node_id = generate_node_id(edge.source_node_id), + target_node_id = generate_node_id(edge.target_node_id), + ), + )) + + await graph_engine.add_nodes(graph_nodes) + + await graph_engine.add_edges(graph_edges) + + return data_chunks + + +def generate_node_id(node_id: str) -> str: + return node_id.upper().replace(" ", "_").replace("'", "") diff --git a/cognee/modules/data/extraction/knowledge_graph/extract_content_graph.py b/cognee/modules/data/extraction/knowledge_graph/extract_content_graph.py index 51bb70107..e52f3992a 100644 --- a/cognee/modules/data/extraction/knowledge_graph/extract_content_graph.py +++ b/cognee/modules/data/extraction/knowledge_graph/extract_content_graph.py @@ -3,10 +3,10 @@ from pydantic import BaseModel from cognee.infrastructure.llm.get_llm_client import get_llm_client from cognee.infrastructure.llm.prompts import render_prompt -async def extract_content_graph(content: str, cognitive_layer: str, response_model: Type[BaseModel]): +async def extract_content_graph(content: str, response_model: Type[BaseModel]): llm_client = get_llm_client() - system_prompt = render_prompt("generate_graph_prompt.txt", { "layer": cognitive_layer }) - output = await llm_client.acreate_structured_output(content, system_prompt, response_model) + system_prompt = render_prompt("generate_graph_prompt.txt", {}) + content_graph = await llm_client.acreate_structured_output(content, system_prompt, response_model) - return output.model_dump() + return content_graph diff --git a/cognee/modules/data/extraction/texts.json b/cognee/modules/data/extraction/texts.json new file mode 100644 index 000000000..de7cc3d63 --- /dev/null +++ b/cognee/modules/data/extraction/texts.json @@ -0,0 +1,7 @@ +[ + "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.\nIt has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.", + "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.\n\tThe point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy.\n Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).", + "Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of \"de Finibus Bonorum et Malorum\" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance.\n The first line of Lorem Ipsum, \"Lorem ipsum dolor sit amet..\", comes from a line in section 1.10.32.", + "The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from \"de Finibus Bonorum et Malorum\" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.", + "There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc." +] diff --git a/cognee/modules/data/processing/__init__.py b/cognee/modules/data/processing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/cognee/modules/data/processing/chunk_types/DocumentChunk.py b/cognee/modules/data/processing/chunk_types/DocumentChunk.py new file mode 100644 index 000000000..53292e59b --- /dev/null +++ b/cognee/modules/data/processing/chunk_types/DocumentChunk.py @@ -0,0 +1,10 @@ +from pydantic import BaseModel + +class DocumentChunk(BaseModel): + text: str + word_count: int + document_id: str + chunk_id: str + chunk_index: int + cut_type: str + pages: list[int] diff --git a/cognee/modules/data/processing/document_types/AudioDocument.py b/cognee/modules/data/processing/document_types/AudioDocument.py new file mode 100644 index 000000000..bc129b66b --- /dev/null +++ b/cognee/modules/data/processing/document_types/AudioDocument.py @@ -0,0 +1,122 @@ +from uuid import uuid5, NAMESPACE_OID +from typing import Optional, Generator + +from cognee.infrastructure.llm.get_llm_client import get_llm_client +from cognee.modules.data.chunking import chunk_by_paragraph +from cognee.modules.data.processing.chunk_types.DocumentChunk import DocumentChunk +from cognee.modules.data.processing.document_types.Document import Document + +class AudioReader: + id: str + file_path: str + + def __init__(self, id: str, file_path: str): + self.id = id + self.file_path = file_path + self.llm_client = get_llm_client() # You can choose different models like "tiny", "base", "small", etc. + + + def read(self, max_chunk_size: Optional[int] = 1024): + chunk_index = 0 + chunk_size = 0 + chunked_pages = [] + paragraph_chunks = [] + + # Transcribe the audio file + result = self.llm_client.create_transcript(self.file_path) + text = result.text + + # Simulate reading text in chunks as done in TextReader + def read_text_chunks(text, chunk_size): + for i in range(0, len(text), chunk_size): + yield text[i:i + chunk_size] + + page_index = 0 + + for page_text in read_text_chunks(text, max_chunk_size): + chunked_pages.append(page_index) + page_index += 1 + + for chunk_data in chunk_by_paragraph(page_text, max_chunk_size, batch_paragraphs=True): + if chunk_size + chunk_data["word_count"] <= max_chunk_size: + paragraph_chunks.append(chunk_data) + chunk_size += chunk_data["word_count"] + else: + if len(paragraph_chunks) == 0: + yield DocumentChunk( + text=chunk_data["text"], + word_count=chunk_data["word_count"], + document_id=str(self.id), + chunk_id=str(chunk_data["chunk_id"]), + chunk_index=chunk_index, + cut_type=chunk_data["cut_type"], + pages=[page_index], + ) + paragraph_chunks = [] + chunk_size = 0 + else: + chunk_text = " ".join(chunk["text"] for chunk in paragraph_chunks) + yield DocumentChunk( + text=chunk_text, + word_count=chunk_size, + document_id=str(self.id), + chunk_id=str(uuid5(NAMESPACE_OID, f"{str(self.id)}-{chunk_index}")), + chunk_index=chunk_index, + cut_type=paragraph_chunks[len(paragraph_chunks) - 1]["cut_type"], + pages=chunked_pages, + ) + chunked_pages = [page_index] + paragraph_chunks = [chunk_data] + chunk_size = chunk_data["word_count"] + + chunk_index += 1 + + if len(paragraph_chunks) > 0: + yield DocumentChunk( + text=" ".join(chunk["text"] for chunk in paragraph_chunks), + word_count=chunk_size, + document_id=str(self.id), + chunk_id=str(uuid5(NAMESPACE_OID, f"{str(self.id)}-{chunk_index}")), + chunk_index=chunk_index, + cut_type=paragraph_chunks[len(paragraph_chunks) - 1]["cut_type"], + pages=chunked_pages, + ) + +class AudioDocument(Document): + type: str = "audio" + title: str + file_path: str + + def __init__(self, title: str, file_path: str): + self.id = uuid5(NAMESPACE_OID, title) + self.title = title + self.file_path = file_path + + reader = AudioReader(self.id, self.file_path) + + def get_reader(self) -> AudioReader: + reader = AudioReader(self.id, self.file_path) + return reader + + def to_dict(self) -> dict: + return dict( + id=str(self.id), + type=self.type, + title=self.title, + file_path=self.file_path, + ) + + +# if __name__ == "__main__": +# # Sample usage of AudioDocument +# audio_document = AudioDocument("sample_audio", "/Users/vasa/Projects/cognee/cognee/modules/data/processing/document_types/preamble10.wav") +# audio_reader = audio_document.get_reader() +# for chunk in audio_reader.read(): +# print(chunk.text) +# print(chunk.word_count) +# print(chunk.document_id) +# print(chunk.chunk_id) +# print(chunk.chunk_index) +# print(chunk.cut_type) +# print(chunk.pages) +# print("----") diff --git a/cognee/modules/data/processing/document_types/Document.py b/cognee/modules/data/processing/document_types/Document.py new file mode 100644 index 000000000..f29ed37d0 --- /dev/null +++ b/cognee/modules/data/processing/document_types/Document.py @@ -0,0 +1,8 @@ +from uuid import UUID +from typing import Protocol + +class Document(Protocol): + id: UUID + type: str + title: str + file_path: str diff --git a/cognee/modules/data/processing/document_types/ImageDocument.py b/cognee/modules/data/processing/document_types/ImageDocument.py new file mode 100644 index 000000000..aa99c672b --- /dev/null +++ b/cognee/modules/data/processing/document_types/ImageDocument.py @@ -0,0 +1,124 @@ +from uuid import uuid5, NAMESPACE_OID +from typing import Optional, Generator + +from cognee.infrastructure.llm.get_llm_client import get_llm_client +from cognee.modules.data.chunking import chunk_by_paragraph +from cognee.modules.data.processing.chunk_types.DocumentChunk import DocumentChunk +from cognee.modules.data.processing.document_types.Document import Document + +class ImageReader: + id: str + file_path: str + + def __init__(self, id: str, file_path: str): + self.id = id + self.file_path = file_path + self.llm_client = get_llm_client() # You can choose different models like "tiny", "base", "small", etc. + + + def read(self, max_chunk_size: Optional[int] = 1024): + chunk_index = 0 + chunk_size = 0 + chunked_pages = [] + paragraph_chunks = [] + + # Transcribe the image file + result = self.llm_client.transcribe_image(self.file_path) + print("Transcription result: ", result.choices[0].message.content) + text = result.choices[0].message.content + + + # Simulate reading text in chunks as done in TextReader + def read_text_chunks(text, chunk_size): + for i in range(0, len(text), chunk_size): + yield text[i:i + chunk_size] + + page_index = 0 + + for page_text in read_text_chunks(text, max_chunk_size): + chunked_pages.append(page_index) + page_index += 1 + + for chunk_data in chunk_by_paragraph(page_text, max_chunk_size, batch_paragraphs=True): + if chunk_size + chunk_data["word_count"] <= max_chunk_size: + paragraph_chunks.append(chunk_data) + chunk_size += chunk_data["word_count"] + else: + if len(paragraph_chunks) == 0: + yield DocumentChunk( + text=chunk_data["text"], + word_count=chunk_data["word_count"], + document_id=str(self.id), + chunk_id=str(chunk_data["chunk_id"]), + chunk_index=chunk_index, + cut_type=chunk_data["cut_type"], + pages=[page_index], + ) + paragraph_chunks = [] + chunk_size = 0 + else: + chunk_text = " ".join(chunk["text"] for chunk in paragraph_chunks) + yield DocumentChunk( + text=chunk_text, + word_count=chunk_size, + document_id=str(self.id), + chunk_id=str(uuid5(NAMESPACE_OID, f"{str(self.id)}-{chunk_index}")), + chunk_index=chunk_index, + cut_type=paragraph_chunks[len(paragraph_chunks) - 1]["cut_type"], + pages=chunked_pages, + ) + chunked_pages = [page_index] + paragraph_chunks = [chunk_data] + chunk_size = chunk_data["word_count"] + + chunk_index += 1 + + if len(paragraph_chunks) > 0: + yield DocumentChunk( + text=" ".join(chunk["text"] for chunk in paragraph_chunks), + word_count=chunk_size, + document_id=str(self.id), + chunk_id=str(uuid5(NAMESPACE_OID, f"{str(self.id)}-{chunk_index}")), + chunk_index=chunk_index, + cut_type=paragraph_chunks[len(paragraph_chunks) - 1]["cut_type"], + pages=chunked_pages, + ) + +class ImageDocument(Document): + type: str = "image" + title: str + file_path: str + + def __init__(self, title: str, file_path: str): + self.id = uuid5(NAMESPACE_OID, title) + self.title = title + self.file_path = file_path + + reader = ImageReader(self.id, self.file_path) + + def get_reader(self) -> ImageReader: + reader = ImageReader(self.id, self.file_path) + return reader + + def to_dict(self) -> dict: + return dict( + id=str(self.id), + type=self.type, + title=self.title, + file_path=self.file_path, + ) + + +# if __name__ == "__main__": +# # Sample usage of AudioDocument +# audio_document = ImageDocument("sample_audio", "/Users/vasa/Projects/cognee/assets/architecture.png") +# audio_reader = audio_document.get_reader() +# for chunk in audio_reader.read(): +# print(chunk.text) +# print(chunk.word_count) +# print(chunk.document_id) +# print(chunk.chunk_id) +# print(chunk.chunk_index) +# print(chunk.cut_type) +# print(chunk.pages) +# print("----") diff --git a/cognee/modules/data/processing/document_types/PdfDocument.py b/cognee/modules/data/processing/document_types/PdfDocument.py new file mode 100644 index 000000000..9402da7c9 --- /dev/null +++ b/cognee/modules/data/processing/document_types/PdfDocument.py @@ -0,0 +1,109 @@ +# import pdfplumber +import logging +from uuid import uuid5, NAMESPACE_OID +from typing import Optional +from pypdf import PdfReader as pypdf_PdfReader +from cognee.modules.data.chunking import chunk_by_paragraph +from cognee.modules.data.processing.chunk_types.DocumentChunk import DocumentChunk +from .Document import Document + +class PdfReader(): + id: str + file_path: str + + def __init__(self, id: str, file_path: str): + self.id = id + self.file_path = file_path + + def get_number_of_pages(self): + file = pypdf_PdfReader(self.file_path) + num_pages = file.get_num_pages() + file.stream.close() + return num_pages + + def read(self, max_chunk_size: Optional[int] = 1024): + chunk_index = 0 + chunk_size = 0 + chunked_pages = [] + paragraph_chunks = [] + + file = pypdf_PdfReader(self.file_path) + + for (page_index, page) in enumerate(file.pages): + page_text = page.extract_text() + chunked_pages.append(page_index) + + for chunk_data in chunk_by_paragraph(page_text, max_chunk_size, batch_paragraphs = True): + if chunk_size + chunk_data["word_count"] <= max_chunk_size: + paragraph_chunks.append(chunk_data) + chunk_size += chunk_data["word_count"] + else: + if len(paragraph_chunks) == 0: + yield DocumentChunk( + text = chunk_data["text"], + word_count = chunk_data["word_count"], + document_id = str(self.id), + chunk_id = str(chunk_data["chunk_id"]), + chunk_index = chunk_index, + cut_type = chunk_data["cut_type"], + pages = [page_index], + ) + paragraph_chunks = [] + chunk_size = 0 + else: + chunk_text = " ".join(chunk["text"] for chunk in paragraph_chunks) + yield DocumentChunk( + text = chunk_text, + word_count = chunk_size, + document_id = str(self.id), + chunk_id = str(uuid5(NAMESPACE_OID, f"{str(self.id)}-{chunk_index}")), + chunk_index = chunk_index, + cut_type = paragraph_chunks[len(paragraph_chunks) - 1]["cut_type"], + pages = chunked_pages, + ) + chunked_pages = [page_index] + paragraph_chunks = [chunk_data] + chunk_size = chunk_data["word_count"] + + chunk_index += 1 + + if len(paragraph_chunks) > 0: + yield DocumentChunk( + text = " ".join(chunk["text"] for chunk in paragraph_chunks), + word_count = chunk_size, + document_id = str(self.id), + chunk_id = str(uuid5(NAMESPACE_OID, f"{str(self.id)}-{chunk_index}")), + chunk_index = chunk_index, + cut_type = paragraph_chunks[len(paragraph_chunks) - 1]["cut_type"], + pages = chunked_pages, + ) + + file.stream.close() + +class PdfDocument(Document): + type: str = "pdf" + title: str + num_pages: int + file_path: str + + def __init__(self, title: str, file_path: str): + self.id = uuid5(NAMESPACE_OID, title) + self.title = title + self.file_path = file_path + logging.debug("file_path: %s", self.file_path) + reader = PdfReader(self.id, self.file_path) + self.num_pages = reader.get_number_of_pages() + + def get_reader(self) -> PdfReader: + logging.debug("file_path: %s", self.file_path) + reader = PdfReader(self.id, self.file_path) + return reader + + def to_dict(self) -> dict: + return dict( + id = str(self.id), + type = self.type, + title = self.title, + num_pages = self.num_pages, + file_path = self.file_path, + ) diff --git a/cognee/modules/data/processing/document_types/TextDocument.py b/cognee/modules/data/processing/document_types/TextDocument.py new file mode 100644 index 000000000..2e5bf4452 --- /dev/null +++ b/cognee/modules/data/processing/document_types/TextDocument.py @@ -0,0 +1,112 @@ +from uuid import uuid5, NAMESPACE_OID +from typing import Optional +from cognee.modules.data.chunking import chunk_by_paragraph +from cognee.modules.data.processing.chunk_types.DocumentChunk import DocumentChunk +from .Document import Document + +class TextReader(): + id: str + file_path: str + + def __init__(self, id: str, file_path: str): + self.id = id + self.file_path = file_path + + def get_number_of_pages(self): + num_pages = 1 # Pure text is not formatted + return num_pages + + def read(self, max_chunk_size: Optional[int] = 1024): + chunk_index = 0 + chunk_size = 0 + chunked_pages = [] + paragraph_chunks = [] + + def read_text_chunks(file_path): + with open(file_path, mode = "r", encoding = "utf-8") as file: + while True: + text = file.read(1024) + + if len(text.strip()) == 0: + break + + yield text + + + page_index = 0 + + for page_text in read_text_chunks(self.file_path): + chunked_pages.append(page_index) + page_index += 1 + + for chunk_data in chunk_by_paragraph(page_text, max_chunk_size, batch_paragraphs = True): + if chunk_size + chunk_data["word_count"] <= max_chunk_size: + paragraph_chunks.append(chunk_data) + chunk_size += chunk_data["word_count"] + else: + if len(paragraph_chunks) == 0: + yield DocumentChunk( + text = chunk_data["text"], + word_count = chunk_data["word_count"], + document_id = str(self.id), + chunk_id = str(chunk_data["chunk_id"]), + chunk_index = chunk_index, + cut_type = chunk_data["cut_type"], + pages = [page_index], + ) + paragraph_chunks = [] + chunk_size = 0 + else: + chunk_text = " ".join(chunk["text"] for chunk in paragraph_chunks) + yield DocumentChunk( + text = chunk_text, + word_count = chunk_size, + document_id = str(self.id), + chunk_id = str(uuid5(NAMESPACE_OID, f"{str(self.id)}-{chunk_index}")), + chunk_index = chunk_index, + cut_type = paragraph_chunks[len(paragraph_chunks) - 1]["cut_type"], + pages = chunked_pages, + ) + chunked_pages = [page_index] + paragraph_chunks = [chunk_data] + chunk_size = chunk_data["word_count"] + + chunk_index += 1 + + if len(paragraph_chunks) > 0: + yield DocumentChunk( + text = " ".join(chunk["text"] for chunk in paragraph_chunks), + word_count = chunk_size, + document_id = str(self.id), + chunk_id = str(uuid5(NAMESPACE_OID, f"{str(self.id)}-{chunk_index}")), + chunk_index = chunk_index, + cut_type = paragraph_chunks[len(paragraph_chunks) - 1]["cut_type"], + pages = chunked_pages, + ) + +class TextDocument(Document): + type: str = "text" + title: str + num_pages: int + file_path: str + + def __init__(self, title: str, file_path: str): + self.id = uuid5(NAMESPACE_OID, title) + self.title = title + self.file_path = file_path + + reader = TextReader(self.id, self.file_path) + self.num_pages = reader.get_number_of_pages() + + def get_reader(self) -> TextReader: + reader = TextReader(self.id, self.file_path) + return reader + + def to_dict(self) -> dict: + return dict( + id = str(self.id), + type = self.type, + title = self.title, + num_pages = self.num_pages, + file_path = self.file_path, + ) diff --git a/cognee/modules/data/processing/document_types/__init__.py b/cognee/modules/data/processing/document_types/__init__.py new file mode 100644 index 000000000..6e8dd07f4 --- /dev/null +++ b/cognee/modules/data/processing/document_types/__init__.py @@ -0,0 +1,2 @@ +from .PdfDocument import PdfDocument +from .TextDocument import TextDocument diff --git a/cognee/modules/data/processing/document_types/__tests__/PdfDocument.test.py b/cognee/modules/data/processing/document_types/__tests__/PdfDocument.test.py new file mode 100644 index 000000000..d8e6c2076 --- /dev/null +++ b/cognee/modules/data/processing/document_types/__tests__/PdfDocument.test.py @@ -0,0 +1,13 @@ +import os +from cognee.modules.data.processing.document_types.PdfDocument import PdfDocument + +if __name__ == "__main__": + test_file_path = os.path.join(os.path.dirname(__file__), "artificial-inteligence.pdf") + pdf_doc = PdfDocument("Test document.pdf", test_file_path) + reader = pdf_doc.get_reader() + + for paragraph_data in reader.read(): + print(paragraph_data["word_count"]) + print(paragraph_data["text"]) + print(paragraph_data["cut_type"]) + print("\n") diff --git a/cognee/modules/data/processing/document_types/__tests__/artificial-inteligence.pdf b/cognee/modules/data/processing/document_types/__tests__/artificial-inteligence.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7de338b8cfe5ec9120e1fb0b4a8d5dbc541b52ca GIT binary patch literal 29616 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 z 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 literal 0 HcmV?d00001 diff --git a/cognee/modules/data/processing/document_types/__tests__/soldiers-home.pdf b/cognee/modules/data/processing/document_types/__tests__/soldiers-home.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e453ca4bc64157ac078193238ce2a1f5982b557c GIT binary patch literal 33733 zcmb@uby!?YlRk{Q1qi_cg9W#lVFq_6xVyV+kU+2mLU0WdAV?r+a0o8J-CcrPa0vbz z@;uomyYGJ2?)AMpf6Sce)7@2F)u-z2u2W5?BreIy$p*rpyN7)+pa2elqlpa$KR*V$ znwOI~fL+Ph(i{W!?PBiW2H=F5GGH#f637IpLl=yJdcAe=w|ln1Df!7k?L;0CMa z3gG&yo{G7vqq~c#xhnwjt3Xf?!`#8_q5p^fzv(EsIGU=Oy8(3BVY~p?)yzHJ0PHgM zFuJ0D|BC(nD+8k;38MjcU{4YV;Qot@BnZIsyZ?VkJn-rqb{ z>(9q*>+(@o_qIat#;g_&uWr}-n){8$53i1nmr57kL~$TLaXB0@JF!3X`$<}?%r?+G zA9xSRzsD}U_qyEN?PK4JZ6nTpDyoz{`8L@40&m0O(TX5u`A9Ls4a+j*T~i40YK=(Y zitR8bl)Cxm<^68W_T6stE7DIwh8yl5GB*hYC)xI0kloxG{P=jCS3Y@spnK_4cW+Q4zkZ#~ zFJ;>xFh2aXoBi0$%V4g{(o3>le#83}lkHBqACv9#C`bMCY{V_wY0{<%#jdV1^}C{X z3j3g4gQb=93zr4QYwd%N?tP88e0u1OGhTurBO!M3_-W7ti6sg$!-yaR8F-gYwQxB} z>GdY_xHU7>NHO|U6D16PbaH~;TPPKG_a&hcopiUC`lfmDML8SEVxR&4a(B;*S`9zL zr>niq+n4y{@20O_&Oniqh~0A7kw?WZ4BX8|v#SP&tm|Kx^?>cQiKgXOp3T;A3ZB2w ze|2(gdA3LE%f3We?#w_|ScZ=z?r+z!C%nMRP&WTYB;*?8h8+}ts#rihQjnA|Wq44N zN{}l+QZeIs>qoOt$_oxwUMF`YB%cN0*=Yq!J8%?M+bPJt5o|>(?B_E>Z3UWH6QK27 zf<8^!9s`+vdYcw({F)WBoUXkrze)7<>tU;k4YfBN&^|_{^?Ob$x2@2a zOzHiFJzlrJF~hh%O4Y~X5>%i4AY-aP#T*bvGCQr?YG>tBfInV-mifi*eLQ&DSc$_a zzqQ5q=1sUBA5O*N9`&J|SqM>&Fz%wVVcL`7CG8$1CaPFX-?fjsW}4I}(u9C(N^e8= z{A$xvNj_Gy?HRlc!V`8T)3~SdDSb{vS(qdp*eaCIcw@VEgjWc--!V2t2Vuy$Q7V5~ zf1#85NxtK|ocAPxB8B2}p+%nOsgbq|Oq~YVZ@ZCtyUD^?Zm*c4faqlz7vJ?a+$X%K zB6`2A(SDVlUufMRvF9g8>ySVCQTxTHwDpwX82su7LqY4d7B{oxl3LuSGakJY6v>00 z+*?W!s--wn9~q~6vLde;uf=fdM8aH70Q3$%!rp181wBP#PZX03gN2hWz3lm-0{ti^ zDLZzg{z0~L8vKVZiXW@`6J;#jGkH^NZ~-V;17d^fQZw9F?~4+(9+w9qjmVJ&VXNhD zJ+33;mfz{;l=DU&2~=g&jl9ZK*w`vPmCKjW=!k?&2rc3@Epxv6;^5#r+ z#;V`y!yT?NRJQT-oM?C+gK6%n}!kHrJ)kyNQT}}xoG$|0|6F&O68Y+sKsAE1{ z`*QK+++=aP;?DFE&iiy_Y}ev;`R-oXHrg2qv)Gll>Z=r&9YKRejPDMo_m;JW$e$~V zZ%!KQ6cCsa2MtIPYfXJT)~0-65rVm%BU4~d$9Q%6HKd?Iy*_3GXM~$nrOF6#_ftR7 zZQ;u>#xSb*K4#I6&jvD4-g)Sxc+gIA43qMH@%E8 zfFZft-|koyu~gMNbqqc6rixX(J$8iT=ldue%{?Am#E1x-3CqjDV~lVd9-EH`LLelm zPdoVuYX<7#*UpSpGNix?B8ehfJ~=z0PO1On|5_Gf-+ZMZRNXR|4+$x>dW&m+hO;o}r%DA^M4Ev6@Ppx;eP4_K;- z<~#s230Uv4D}iQ!M1vq4EgSQ}{$xVw-Nx4gHi1I?9CVi)G{tX*eDs;bRRGjpX7=-v z<7~W2^g^VCfk|lUt<$|&jAUC2AF~dtL&4;yc0Z)a zj4o{s7yX0L(7r>F5i&z0xnFt^GNJrbmwLm$v8PHjn?`Dl*IJJ*Gh^gy%=FpU48ez= z*QV4_UE0#4Ejl|LH%r-vb;@^4o&V8`%=*Koafcs1KqmWXQsh#tqEg=edQOyLI?{d` zln+@W94xwr0Otq~6;fg(oIbMm3FRa9%G!qTN^_2*+rI7b`J3N#G*63XUfUD#4ch~; z+}o#Q(KWnCGJ}F0G7a3{4`f4Iy#u)P!+LW_i62vaN4MhdCG|D_V0)rk6?C3mw{I?) zuTGJGEAvvQ8p>xrU9=(?BPFIf{#;{goMa_%GT=F$v31?1zP&097-vJ*$X>4D_84J_+vk6Q{VBx_gZ`IRJZ7Xb((~4Z7Gm+NMP(FhA9J^<=o25fgawuOd z#Bo((SC~8bb_aWr@D1=V`$e3SK(P}4nko_N6-At*u9gzbYm zF5%{vHDAI@9VSO()!F0G;1F2Feem5Gkv=Fb^g!YMkf#l?d8XmGi=Mu0Yc=ndt?{0{ zb64UO3ZIT+L&B$Jdj2JwY9YY^iF#8%X`bb3pV^f$B24#Tsp+?f-2DM<#2&7+v0dA& z9W67_73UDieUrLY8*h2xFI|4|qd)f?uUy)vA0Xo2SnO}G2*a2EK)HVdm2y6yRTzBz z2bOaF1!(^PjlT+hqsITg!1TX`qrZs%?)g9PD3J4i#-mj_@};}gj~12;SA>)-ep0HW?1P~K$}E)aqhPkp(z$I&^Gk?wQab+Z(;B(!I7l_At8=0lno zLMSgwlk0S)mw1;dr2XRR=KQFX@@+Q(&x`w<^|4RuC+8PcH*;(m&X-tyONV1`?|iRr zy1ER7g#3I>Mx4VeoL0X`*J+Qlznjq_3YM@Ue22SRadYeaWIX*~=%hkzF*&i>>#3>l zWqR*M=e48P!Y;37;>Z3Mx;0JA8-1|y+h^^S3HrKmOFgc^z(gb5brQO1`azNdTlIxB z-Ae~s-bGNt61~9*gH<+^ZH7@kESHw24v(PLXEJ1?w`$4Iz^{&pYKjUP3wzR^Z+!+;vuvEXko_Lkq=C6(il$_^dA z$ueuEVGkUn8eHm<&0g+S6S&uFS?Kp71ROkf8;n>b%49ih@RlNg zh_$vd8RG#uwH8*EJwDntY|GJ1cCOmdk&w4P~fH&#BTZ?3iRg92QS6cbz zQM|3*R6i9q_Qq~gl1(Vx=E8==s@=H@vJ%|<-olgN3?fdr?$s9g$&T8e@on?R)K93l zc^XbUJV0p_YYKWrcZBM_l|j;~E^R=YgrdKyh|)$nro)a+O~ zr2Wsi?q_!rq~OUUD`@YRO+%`zWrb(SoQ@)+--83Hz#qTh1;}EI7TAG9i}=$G(V-DF z`bNG3a~xqE>J*d!MWU~UeXlEfy}5B&xgyF`pXbmzca5KlVrTcZY5$}MHZgmi{u-ZB z$sXzKqh+FAumq*I@Tvevi+wZAV3fY#5~n>)Hg5BAG{4ZnBe7ktgktX|Q!yTl6uLOk zFCrg1547efByJR@5RPKQn8p$|;ao za$29q-+`TX%b(VS5heX;-|b6gWgA5VISYQv z0j=CR-CqPkH!NO)HbGPU-UTWi=QO(-$ zIkmQBTvTM>N>H+cK4~5vnuh;qfcgpUMVy7F;+r}OX&v2l$hj>tua6`Cs^vNf^CwkH z=VCEEau8bEPnIcOQ8tG_4KWgAQ)C{SuGSi}wJLtIIFcI2OkL$%LzSs)O0>kSnD@7vvG>g(K_dK2`?0{_L4$w#WL4i1bT!8F>Q}+Y3Cl%sS%_CU}ibFX54G8kXgq$m)_c zk!RD>8R|SPAn?2`%*La+J>l(yX)3Ce=-MIgyr2peoFCrDtC(iEkE~j_94rQln>2Mf zU?$GS1COImWm$tpBb92gQSy+8Si{6nKy|}qOo3V@{mp$XW}bF#UWECrDRjiUmFl(^ zdtjZ5uS__*wI=%Mo2;f~5sCNM?uPn^bK3n3^R}{!X-KE>EE#2%o*YOJLg%loYE6ok zQ3xASpqZ_Z#WVPx!jB~3GV94DeSYwA-UrbniH47Bwu7BSO(lR_>xb=9f|)H2@xzhM z?>l=_ayl%}lrBEDk|XzO6F6{Nb4d&x1894E9+5F=urxoDTAMvy1o-E9^?tl28B&sv zzdJzarO~HAj*wgx4OgfK9-_quoL+l0IOAw;q0iHIuw4bEmPWO_R5aFI_1c-oSz^pv z*!mWgJSdWBSH4l*md`=PHvPq2MNBVhqw#a4RAuOFIHD}fPqJg+HeKHe|1@u)ii`~bhVd7mUS2B_ z9Xk{BGYzeAO_q=Lo%*gyo_yUhn_m<_Z1{PI53Pc{C+@a>5i^l~_k5rAh4g*uT+pzX zUv3EnL3+L4sSM*+6r$)hn5YSiz$vL9Vpv zY+G6{*z3BNCU8FGaCjv&+TlX;-(b)`w-f&z3<~-e3<~~L@&^WeDEN&O|8Ftq1M%NI z|HhykAmIN7gZ7oILa-J#nU4|G&%PM6WWE!j6n??_qhyPEN+y6!CzCjH$x!!^eOQ(m zv+FyNXLZ#q%KR_MRWvl~ZmuO+?=SO9PYjbBn_t~rZ{GYo%Nv@y?32LY(k2N4D>Lr~ zf~H)Pn)+WE-qq#XTn#y1W__Jq&%&aXq+fOO)lIw`(MxD*x^=$XkBbMgWn8SA=BVvD z*1X(Zzpj26vR+}3G_(ukFYV)J^KIw;u<1PHSS5I>)nuPOw!fR>HQBs*<2$swsi@Pw z>7#n*^VIevMeAAgD@m7DUPK>dRX>!C_c1I~OD`1bMi-41_@U|a3saYu5*Ag1D^2yi zOQnuNhJK#)H!cX^ClQAVBu{xWxggjV7<3E0K04V)-Dn!aUl0hP&+f4S^ui9utMIL^ zZH}qty_CprT;Q-4vdgpmxoOWi#3QCiWEF};c)F}K73{MJl6@$y@MNr zJ>1G~+Lj`F$(E#$i$Aut0pa}!wN>#4Q@9|R7)xO`IgNam_i*M*auV*W7eNVJd)CEH z@@=fdNs`K0=dl9f4$GfQ!Ozg@+Wnc>?G6(I#^fMk!W+{-oYf@o$?d%#Z|%N$pD3$L z$2ad)(k~ZQpf65hjA_2Y&!nrJAfknPPwmBS-QTfTlYUG<}EKjyRBow*11 z8ju39a>=GGA^uYEC$hm`XwBNSc6^FM7pT^pcis#v*nBI2$Mkl9%SMv=FE{=~SX`*eTZqwD=NzCx$sOMT*G#`C-wpNLkvHOcp%{cW|jU=o?v?0gFp065$*Qsd^@MTW3|-nB|MdPjma@?T6k;85Ee6Il15Bw;xw;)$dGM;ZQSdR$BrD-zlE&y0Rk+{-bURTc%wkZ z`N%^oW9YHC7(UxY6}_w%s^DZvE9@8i1Wcz{-P!LNmi)nB#EX`zU-`U?kF|~5R(YdJ zoB9g@Udeg@`3#)IsIBXHuVi6<*uAIk%hM16`Cb)|c|6IkXX@Pb2b~p9TgI-ik9$JA z6Go}UixIl!BOCHu4SF5QAM0ek2yqps$y4L%ev2rGmLOqf1oz!+5yKe3i?N+;EFQAy zSUM@e>%CHx0oHtS*1~b!7_pen&&D06=}n)fr?uxT>c1=(_cbP2n^-(eJA=ELZzX&}dDM#2?*8?wKA7hc~f8Z_z3Q$TC6$QJ7PuzGJY6VMO(PwGA3Ad z*^)>t&>SzfdVXNV-P_YYkMde`5u1a!jm!UqG-#*sr))CZlPZ6dL>+yVkoENUINsd@@Ad=le!bp3aI2%A& z9$d>bK+JkxkoOt3a}uIlizbiv-fq?JG$Ll#4&Re*v4bJ4lHdZLoK|qvOuHlcMGRA; zGe3S~s0J;~GyXD}&;48X@JY=Cx&ICPc?h-sMh^cD{P`;o{O1AprY(x9`sw z^#3jV`7`SLH~irQbN(+v!d2RTz#oa8a@x!-lVQ|h{de`uUk}f6gr9(fIfa{>%SC$$ z<;}lmert&%(@pGXZx;&-C}h2F3OF|G|MAuD>&xr*{fy?xIY*&awIzmZlP!dH3X_(o z#tIe9f-iRat}c%+ka5OddA6rIVXuFZf3`WZv3;eHc-Ldts=svCaC7&8)m3{pw#uW7 zNc1wTPe4=fM+j{_E@d^W!XUpr(? z5SiL8?J^5Y z6*~&VC{V0z@m?ZEeSv5($3JX=9$n<$A3oz`gVIFfv`)g33hzldtQ2(uM0FA_1X15% zW4)a3^T2G=R{CUS7dqMQZ(VEc&;TYPFJGx9)5SK7Moy!{oCA|IQZt7pbO6aQnHRg< z;Udlsu*4CPTIyGH0$0eVZKmWhMZi?wIQ;D%3F?V|`LcXkONaNefSjtCFW4YO%yxO+ zlKZTD`SIuKpb(v+vD=f4X|xxcJhDaxjPACJ*YShefFwvBM0X~EJj z9PbgkjFJx5;D^79VDOTkz#pUE#NDa3&3OcmHvgJ7lVmx)Ljr$|#*e;BkVbSXULGw< z!OMT$I^^{XAy@iK6>>?e3F4o@j|xOl&h3%3)4dxMJ_^TF(oaTH{ zsp{;*njTwsHEGlk`q{KR z;(}C)%3X0_eMGyZit}uCuPO&3`;3*5wVRg_JKU?m#dh%cnm?5W$CcrL$CJCbRNotnSp|W&>Fz+7@zTc9z*m6c*kE* zIVINrkRqYJK%wQ%f!V#MFaGg~0SeE}qWKOgNrq_Co42ad5);T8#FYkJ9XQ7Yt@(`p7JTTT9X#C@X3mp6&V?zdQ#j|HM4e(zYNn zF4JlP3BK`ExNv#IZ)zc(ZH*3xmW=vn!adY;kU~!6yg`spdQf|FrYHW=RAtbxg#eE3 zvGx^G^&9QY~Nb$?;NEOTOna6J3Cv*ZJ#$zIwBk0iJLj zm7B_&B28_#`-6SBr0is|v@{hK@>%#O9P;uh3Gl|-q@;M2p`MDkXv*a9Jmnyzn-y00{&`K@{`V{+sWdp8~LB-jcsR(tE)H--jrP>SP2LgW~cfH?f3RcE0Rw zF*BK(C63v6vSgl8&r5Fflk>pXZbJ;^O-ll*%S>=Xf$Ot5y0<|w{rSoaE~bS)X-@c9 zW5bj3MyC;vM;V7_W@;Jf@=gJ@6wXu>iSl~FRq2BF1O6K;_6m!OiWCap!V%XmytA0E9{I5O<_z=ALzwk+ay*%`XPXhiGDEh}I{VMoP z>i^a!JrMuh^KYNT!TrDRNsU?qVe{O0O&6*^k+b6O=+J!7X0X>1hikr|M&%*;NCS}0 zFEtYj*UDMsYXt0w`8E2=3w8=i{mgiTuY736geWICe486?ovtr3w$ImBuZ^$V;i)2C z6AMex6=N#kM#tT|j?Xr{#n$;aV|hvQ_Cl*pVKdPm#T`qjVmMYU#!DYH>xJFKxuQ0xNL3sd-79ge!gh?SmPG0+`mw};-KmP!a-x*>?E0H+O_Sg( zR|A>GhkS%vze#fUL^bLhNeI}aRH|9ENJ#`edqcsF9c^vrHrcyDu7A>lS9b>j4VB(N zm;HRBf2zkB`J+N_(YHJ-IXSza&St1isL#jQ(HQn30+;r-$Q3h^h6YyJxxpuc5Mogv zCLcA>lD`#Yy+K+HtxTC4J@`W`sV-uBnuhAk4>4hv?0pk6Yf*Y4$oOHIGv`;jT?#9j zcr}i`UithslsOQpd?A)gd=||>QK!ZM~qC-#~!?be9p~tOT@| zZ(?^Zem-?e3s>pasgrEK|9aSNi36!Sr>jo7B~@SC{iw4+V~Hj=^8e-!Q8-J+>HyBwvTG=g!~@{#TFMG z`7#wuR#T=8B5O++=3ye`87i+;RLj&^_=WQ2(C-?7+XaJO8kxe{MnkpIXvi#Q&=$g+Tuo z0rp0noAfNM`&YXqZS zeYg`euDQvBeto+Mw@JlEfa(VMu=J_;m6K)VX3dgfvmfG^4jcr&1sN`{PyPwk*yB&O zX+Kun;1^QwjbSB8hD)u7`y_sR&9`n>cl)O&pf;?*>2OXded0|GV@!Qy)l;A7{F%#jO<`u^mY)B9>*=mkfM=jWDEIDO2pb{hpI(zGu^YagV|;6G~A z;xAMCxB3HwobX!Ye_CiQRTV`q1X{yCE^WU+8-7Zomw_9)sI+^lEk&MkVg0HSd$=*0 z6@A82o<7~M#_`EaeJ1Zte(1AY^cN*B)Vi>0?ZMfR5l}KKjd}e@haV%JZeo?!E6dY} z7z@%&JhXdH(BYBd8l_5=dhroryE;j!`#K}_grb+BDqw4edxXVf^zbM@IJ!?Siam7? zSi?9(IJJE~a(9XQi|)K8qg_NT!;KS)n~y+KCRL~HTyK(QVmCkg%)xn*3|wv34Mgp3A6sw(f1R!3yA!4aWk$s*H&gb;q} z6I?87+-4E4>A}6ju_>QMP~XOB*I`bh5lLL_0sw)@0+qrwRhF|d6JJ}<2mptxE(atj zB|geg1ZjP}oWSe(Sznx24^od#g-ohUEwtO# zbj`}lLQZ#is(j1x$nLEzs{}|j(i~B@EIqTNx+xBz>n~p2GVlMH(KTmPXY<9b+Y+Ta zz!TJi9~axr8)kz)mF16zBr#S&n|ookn;^cP1+vEQ%;81g2!ySvH*k_Dm^yMDZMq1VJf=Z}Qu<;tIO^PUF@Pl1ecg*%$+?%C6lM(f#gL zOw$Vd*lS0G&$S;*#rdO%W@E=k97_=DA}CWsGv|9*jFpRegaIjR!rxy$`%34LPj=nV zw8@e)ABhlZzpgct?^Z1JA#^gwj??-iGluBGL^TG=M7n%4t`cHpTbOvGrrlTk+R0JUfOiJ zUUL~Is7#P>^i;wVdAa`IN2juC-(Pt%q5ccoguau6whe6cSKy1RsSi-1AbI zHq+KIzhH5J?1`%@RmCT(%0#X@pEVp6x4K-mB)ZJ+#I$HvfATKWhRC{m^}|f zX7}<}Q8-$!GoLPfCSTw_TJY8(!|2_V-PfH&-P%+;p4-scO^)e)C7Nu%NHn4wux#w= zHLfg3jLL%}tF5t)$_%l?4X+T!CX>Wq37>%|(pl#23s79CZ`zrjMC4@b+z5*~+UJ~e zXYN+h5i^8n#6!axA786UsLMs!&@sTBnnD~mGLc9CSPAS#BZ!Oz-&;Z>^ zB%`2;UK+?B+Y~jMaKz_~n(Pu){mwM`VA!X4B7|VJc#wyk>j_UPeBct_+ZW}cW4&(5 z4BhvT}|68y8XWaDn`i2t<{+~mR zu=P#kJOrz02)4c{h`uVL19VeK>t@yvx-xseKT_}~*8!jnZ?gV$ubU*2wf5Co4>^ zO>wcPn&vK{lYwv9&wH+=fm-Rl-x#?WH|eKju-=gK_6(!lnE~zDQ8}VN3(*XI_aOXE z*f~5M&(=v#Igs;ZcG`kqHH@`u-bU>)<{m+>x0&ID%S_a%Q`)2*z;uPNu4ckwFhs`z zWfHBfwqz)Ls{PI6vyd7w6vdFV7`eig`Jsf#ymQwNR-GBFi9}4sa(EG%?V=aO;K^qC-fYi}!ab2p z-OS7OW>H)FixURf`21cK!bqbivbP%dCETj1Umw-1EURkxOitulMM@KtT$1sb+hjTr zB#|8?fIaj5+XCk%gUz(U@y5B9f9!Ymy^Cb`D2$Ka-n1i!V=KtxJ>T``RRNujLij3u z(%Tl=G3Z@%^j!~mW6G-rp9z8Jq)Ud}+z1;+80`aVK9p+?ee1iBov$>0=BIbR6wNR3 zT(E&R((`k0RcC=UBk38gq`&YBsWz?yv~=D`UaiMdicQKJ&&I_V8C~x%PgSHBNDd(Q zFR9(uD38~e>ujE7zdTjVOB{bWTE-@?XJSo>Ehw-yFP|*J=*v1dxZd}n{Mx`aM#Tl+ zdcg{m!ha8Uf-U8O8-1c&T)Qx;=ZNt!o0H>12FqgG1&`iB&E(no`t{!TA?vLl+c&q~ zU@>@lD(4$dsoccNHRFw=4MGlX5MEdL;eQjLy2TB)h424YBMo}kD*A0X{~aU!cP`sM z?=O=m1hHtjd;AnJE83Sd42c;a})W|m~Ea5ES)+*n-#LJMAD~gh<9!Kvv znT@?lhPUQ6z|F|;cRvz?TZZSjSGW;RU*$X`<@FO1z&%`Yy4gJ3JUToe!@9zgl3L_! zYZ7ViRWt!FEOIV(;t}DI2q&jravrCTFS0Oamh~E#eW<<~xD*(i<_^R(It&0Qx71yf zzczN`tS$C#`=)8M7YYSM#Kj#t6QP~@KQZXj^|=8zR)oL4epY(cwXe6j@Oe5d@izG) zFfWe`S!&Y$$x=6?;R41z4h7^q@Hl&Uk&G#Ggd5|NYpf2wrl^AGd5XAmR*xp?H>xxZ zmoX+{S|lr#G+9D-VQIG~GjRF{Bi%o<_6&kM;$*Ryy_KY^zNlfx^g#-mH00F~G$`dv z=wm>~YB$QK60fD4-{x~Sty)@gT=qwVQeBRte<~pT76Ur1aPl)<4xZm**dkC>q!uVK zYEC#RiSs0#D(XamG%e6|XVYSbF@IB*iI!LSfvwWQDfvU`gN6#rgvQERqs4TknJkTm z1dgm^kin)Q2wm%1QiT$4SV0ZDVM|mXaZK+^nx+6^`ypRuvH7{DF zZZ8q!E>+=y20i2D9?EpCn~cnlr7wCHL@Ky-z=Fd;Ku?XxqVf$YCEtK+iIX4a6uzxv zbRD0u)Yowbd^7v(tLG>k=Yfx%SihT@{k`zXj?a6j2F5cZ9U{YT`5_`VP zC!&``jv{gfo@i1A2{A-h?d3MP*82z#l?aOL%Bd6+Z_;gXO(Trp|E<-9%A#2{-iL|n-Q?Bo ziLiqwM(dE@v1Zibab61Dp&p{=ODeSWrITgt$a1yg4qM{TQaQ~;(9NaSdJOin>6=b` zHsVAs?RJWO3dy_5a@cE-I3|`e8YTI_3|LLK zQ^&;+@Vlmxrn9Iflv$RBf$`;2#_#2N28w;^5@u-~85YX=br zSL@#ee;7{CpRwhCXo#D;nz~p!!B~X>UKmXUV|!RmwYbj1hgr(p(Z$l*7od_K-joAKs+1}01qdSjgx~11m%L| zMa#Gu+gY26I9S@512{0)MO;lE61I6@EqQo=oZPS%zaDsbD1&v!!v+L#1G!;i6Ek*_ zHn+C4`p;Fh{w{-cr0QmFukq011N*SlX>%X|^w)yoANhj*b*1u`fd501Vlv_nB@cpu z`I3L+{$C{ltEcMa3L`1wVBz>H&0EFX(i)ZyP%x~c2dx8nfNX#1AIt@Y>70`b0s;WJA#9u=m=-~>PGK5_ zLP0Q+KnM>TtWQ|~5KeA32p907kP8aq`GI>_Rp@_E1;cv%tNZ_G!^Ht+<9?VKFrGNU zY&>92Fl@+RAWS?Dd~iXy*myX9$%%^t$OiuFHk1p(1_DDNTo70VPS`lPVEh5VJg|xS zOC$g&2PaIt4_pJFut9V1{8bmk#RdU`Vax&`Tp%`Xj$e|7f?)%M5rqu^3W2h5aQ}J) zVDez&hCB=w0D;0}^_PNpU}JgE4@?yhFigO|>w?%GICu~->@$)^p|cP2!Z}q z)319VZrIRZx_Zzi7^Wsi093G=y(R;)hP|(vP;fbhU=5Ib=y4 zObB8q@H@%@+h}=6fVdD_`@+(F`&Wj}J{$IQrOdSKlVA6be0HZSbl;1NxmOLCK@#u% z;Np{edH&TE{u#{u#|iuwj{>u$|KA4iw`=)lQm{(@Hr-~%FbfQ`qOJhlUlvydHjmUC z)g7!Kj<5j0rtN=zk?OaTg&mghhpGOT<%*aw%yT$eKAiDk2|KCduZ&3c2S?=!_{-b= z)A~=J{MYz?HF`Mt!yRUMVNOQQ+6>0tuXnltzw$O!0Gz+v1%UGxe}G?6dli@!ec%=V z{Hx}#RTOME|4{mkDIQMxfSGaFm|<4{z~6l7V*IN6PxW6e>G#^`_qv6Plk*(B`|J2?MXuO%oW_?v75+0^jH(ii7T@mo-(??G7Z+_kHEEy+HA zUyc5H&(uZs{@L9C^U3WRQ{}=}?{=<27x!&sI8w`!y6*-1byv^f_t}be41Fa^1PhVi zdNSZTk`RneUe{;rWxpK>8CdMLQr#j>0MM*CQc#W74{_&r~{Sf}LblKk~RBhjQwGnbw3w1#DdS?oZ`(4zf?upz8Esg=F8V%edRD*)P>(SjLj!Q3M0Pwz#rh2lE$v#|AXCT>4cRL}<_ z%=eh^<5`oIt@m)nnIuPtPcwb@_rba_77iKrtM7cNgqeg?=l5 zDkwTN+>WM&TY?Dnm*qfoTbEkG6%;4W4#rxcO@sq|9V1wFJoIwHn-9AS&&;r+$)J2i z&?HGjP}t((R;8Sk!hn1os`=KYbsYW<)of{Hi7I%itqkat&U3({m`)+YOgmVQ(d)p6 zyDe1lO5wh4e~9p!>E7mQqFU3(aN%b`yzlE*bhol|%;Sy*X46Rq)fLSWWP%YsGe*ol zYl{G%p+=AM=Ha8oTaokXdMelE&AYh+dVvedx{Q`p@{4TeF5KRkdK}~#F;x4#4_17h zNg)E)6dkvnF;>bm-F`gRzHWE$l?wrodF9#+%y{%6rb=_)p;IByDb}{vRYD&6iZz{n zXIg--<<$_@hs&;H#X;#qqdDu>U!Qvx+{P&L%GL6 zU3y$de{W;ix5#tUgZ{mPGtu|qVw_+(aK7B*-@}!-Zmsfws3AjoDAJ78pU23i$N+OEth$nMVrb}q%O@~ zu}#^R*=j$Zj7!)pO%s|DUYVX4RG0l$dN)7IS9wYX&2e9{IJ@J=7@k|WO1&b%R%WST zZT>E}a^;6HYQgt_yp`d@Cf~?7wWjffr_K>2Rv)IgW)F5K`DkL;FgM`d|VkFy5Hp$;R%L)}bn zt)MujJC;>W$$mF?_u~&%&9}`pbWl6Y62sRQk1A2?lr`6Jb?Fb}8oG)-2?1X)65$zD z^0tg#%E~IiIo`-QHqrhFTQ&Hgsp;>57jfkxjllMuMi|-7F#2&Ee-zk_`DcPtNLoDo zI$d?BOsM!zTEkd{>e$||Upp0y6P!c6nH8W8@F;RK&(UZ>(uW1FckZ<1SQb$01k(aV-)WWx!0In-Hm(RcRpOmmMRv!rn z)W7f7t~~1=BI+`Znj(V}QLqH-_FKH`(bdsNWMXEXNI(h<5dJc58!KzB@>wRSze*8u z?c{oAOEe^5*mE*7pj&>hU|Qpqj9k(m#j5XJ)BfGHlKZXpAWrs>jh<&#oxNnh1jz)x z6*C)yaRk>$g^tm86nN>bjQrE5)`XJtoo2 zIt)g7`+6o|ii^c{233C*KRLk-B}hSHa;3$m?KL#_imK9>StHC8THUiD;vHq62d-DN ztSpXTUsWC#DWPaLkHaj2e%=1d5-h6MYn^xlGOq4Rt+#0U2B)`bMy&G3wmW~mIEE}J zp#KwGdN`|exZ5M3q*%G^dNR>1>`n^tPMw%=mMuUGJ3I=ACs9oIm*g20l@f_8tQPW*O26BjtjkKN2FhAo8K(i-%)gHWZ7TIJ6!41F)r*B!JM_ z6BY;ghUx^Sw+E(7M&6?W%Ho8wN+R-d!b7r@h6Ru2h%$iX)8t871M^*lC5ELir@}C2A2>MZtNMp`6Cyo-;>B) zqddo$=vsl%vP0o+I>eni=}f;@2(B$m(F_lF2%8NIx4AzGFNFv0d)@9_o+%*x&n^=g zvN45%mj>L7zgNLwvbO41YeR#9hVmehCF?peU4-#(6qKLfXimDi-l@Gt=CZXLRNlU8 zG&pmmx!PN~hpiOAVooG}p zCQ7R}CX|P$H#-uL`nPQ|pu8wmIziZUGBJX3vdh*3W!WeTW)=tl5+2Ah#fE z3;hrZZm2mH{WbTLe+7*4A_$@ETuXP_ye(endPc&V6Z(L81+W&y{I z0w;h3pYFfEsQRXF9Jj+$&Q$jf`$1SF;tVAErfa`sS z9nxeei%HeQoKS}=Uxc6;u7H|kZ{!eQ;{Jd#;)rk3tu)&co&>dgzD76qbGW3$_=DvjdRY6TCqsriQCv$X?geC}Q7b5c}d&&0dDM7v7` zCQOn1dh>#a3(AO@GAAs9G6W^TgyuqIgXA#%SF|0v@BhtWw{tKK-obN^qy=VC$m^ z>e6@c_kjnB)RD-PY#E4mQ04}bJ&F^q6&wpVi|O(>8^0z$Ep5)MDNOW#JQ06FW;!o8_P1uUZ`%@1m!N zWYX%G$EMxO1Z&amTR}TBz0k>lz-0jy@73ZvOqWmJTw5ZN9?EU0_bprC^Rvftngx(R z?DDe*7Yp-fIaa;jKbrc$VPlI~_3Xt!pSe@?lOl~zf=@X!BMPbCSCn!G)n zrOjn6v*VB+beVTaCuop)La9Qs>0CK&aIo5Z?uoQy^{h@&AicBHRq{?(zEze|BeCop zJ!N;tXPOkAmtglVE64bXa}z4~;WACeMvSYGTL3B~n;bDSa;Y%u(s3X&D>X;BrCt~P zQ-P^LUPw~BoHKB6%pJF;@coi@#;8z z*CzA#+9co=WgG~3L>a?D6> zp+-d9ArMMJ?W^i?cSGZHcMWS7>T?`tP`SgC zuU?g=m&@>9org=(7mb-%r@p^GxPOg&egrP=B?GFN&Pp~o3vGoEOuV4zTfycRMhq7H zmV`dNEdsn5!a>qFiMH1;FdDBx_qyn)N118@M7$)G>iR@>>i9~6b#_?vwesA6Wa{qq zcklw75~@+Lyz2sMo!7pRzUgK=Ym5m$(w!W7`4sn?A7+=)*N>zF`ntM z*csBarj_)6V|;8OaZ+5?CFIAMfAWImh?Za;zt}9AJ7xFD9r=O+ivekl?H2WkVk`gY zj%Er*L&bX5cWXD^{Azht96q;a3tls|r8on(t54S>JkVCc z>Zqj2{9rH(tGpk=co4RZ zBGAs+wv;pwoa1mIPApakO{{q^7CnS7MoNZ0&16M6b}qq?o-@7dYB0#(`fKSNc`**4 z*$hCbWSV?*Nd7xh09VUo28jYw(|YkYyO&Uezem-|zPna5jkP0wSZy@oPne%lVBOt? z>_Y<9D1U+w{ow-{y|dg7O;KoE6MpKh96?S9BQK>O z4FZ6B8u$!SWY09jo6Kr>sB=0puPARwdy@%~V@xC*_fVkd=-s`jCGAf9TYn+yL_I`b zFcGh%gvlO_CI7a(MUU=<8GMNnkX) z99vMzPNJCSc+T|^m zk=}aY{_C`LAFCMsW%~(Lhbjt|^=rM8`qR0++(;#n;HtddfpQ-u+J-XhmS6Uf@A7`k z!_z3iH~x9(fDqdkMxU3Vg8>Kra`6KU6nSQ(wm8;YDIeByUI#brptCPe%>A#PCXKEd zqaxqY1~lB6?v}RJxhp8jYPDD+!EeQiWz2l$7V`WMeP=Ueu+Ygw4 z43y@dK>SL{<~!_zeCI&dd?$%>6Gu&g{*Eb*mx>D(d}T?L(n$>{s8OKeil_~Ai-?jo zNQ{u!MLlZjvXyG6wS84CnqN|0*6e@o=1+J%r2_(LS2FG`l-K1DA6MJ^v2HZ z5k9<4?LZ8U*)VoTq7%%S-n`DDt0E^kkXMRA9@3uD7^j9)IN3VZMrot^?ym8*jO_TH z8yx*-Oq*ZtBXRyBv~dlBCA}LkJ*=vd)nYkh0N1spGiGM1UXc3a+O)8r3*8O!CM==V zE*(VoNBIN{p3KwWC;~s;2*zP3(y2&_xc6_o>oW z<4ZSwCjdd_g3}391~)co$paLx+c3$q!RUy#6H|>vqhpyN`n%=I+@1V((#@dWNMAZL zi-RBsOwH^4)!>ojPf) zZK$X(c3B-AjPAED{kxJG0B#n#LBEmRDS7GIYLco{3xg)a1#}s)_}J{x=)xesGP^qc zd{=!oB~xpAgl)&)DsMY24?uez-*On_XhyNYx42kf$!sZUco((gw5g%AH4{LI#`i-@ z@`A9+`%#4^(fX!Mi{qVz=&d5s13w9omNH?I(`x#f+r-7v>@S0vqw0FdOxUBP>3i%-9{jn(;q)ZUZ{3!y? zuHcEBW*IB7{S~qBA$~4}P%JxXyM-a@FM-IJC@p5mT_RG9?F5`$#-n8$%_4<>mygnB zfO2eY=iaDWMa81T@i+VlmLE`H$V#)JPCNfG1DE}!=2%he-n)4buD$?Puft>sRg4sC zsC|-z({K9^c+k33?>+{hlm>}o6GI!*2bSoJV#$x%NL~kX}N}i4YMdo5BmHi zu&riDh|0nQsUQrm4ZT1+#53#OpY*2Vao3{Ef;(7`c0CE@5~T?{X2a#6X%C2Kb&yTR zgiYB_ip!v16G&2T!U#gaOUoc{C;JLAoId7QyYCj`uiC&OH|97RZ8s{3>MseGAAJ13 z)@hd1kn~$DRmeSBO3RKuHf6dtjpk{x7gij97tOmHjE4wc0^6*;f9t=X?g6Y<iEV*K}kzR03rA- zCN%yGpm2#^l=9HfqomZS-nEq5-z-`K3Q|OL=e8piAw6+?bonWEstT$OAoD-Sz!5+RfC1&7e?@ z!HcA~3qm!{IIN$?CD7L=4(R;Wj3Vb*6JouQwwCsmPP!4Q(_lLH-MHnj;~%&`5>`Co zm@?pGX2DnLfDJgSmmigM*Kbdr| zpES61F!~x$#UFQ6d-TGtHQy$9n$UK63hMJk9sI6>Bo|p=8m- zS3nFk{a#^USu2ZW6*$a ztm5y4W_PbC!;MJ56CpWuueI*S9QsnZksFS=7mR&biWf*yVE55pD{advpNMdcA~v;S zP%L;XdPdAyEEbeG$c4x)*(zpB2jdZCpi>40mf+U?vLxbw1zS}|imFIt%dKWYQie*$ z9s}!>XQWkjn54 zd0Re`=i81Qi7uphlcefzWrd$zri6!MM~fsL&%`k!rwDF~KCs+Z1`d@08%E-r48t+w ztc5j+1WW5s1pFhUhfz|&T*4l!rBdg{o>wRI)KR^;9h@k$J)QB(vli*z@(?;FIwqa3 zQe2%`bQUyO8`<8p@xL*Tk+S!^j()8_Ru&Xh)j(>Pl_%=tY^-&Eezh&h*)|Uo3q%)H zP`}ClcKD!q8tkhlZPB&gA{WxIOaGpXNZ$#{yK2 zT^kn{p7gS9o-(DnwKa&g;Fews85eD`m8u{Oo_W~$t(#HtV?~CDr=@g%Lc$#3SM17TtVanuxdikpad>hO>_#@Gx=Jw);^Jxz>uMyrX@ zPDESe%#W-JS)XD;0KF%S*k#$+ZrTjixALDws&vF@QoF!9Ie$}W$Dw-gZRSX_&OUT& z-aNZ!65w^~((yFWPu3?VBqC*7dQxgvxMS4a>V0EoObI?MEu^u7(eD=q`JaVVV!d>O zd0GZyHORLqic4v4WJAelZ4o<-oqiVV%Mg1LSiscWV1^o2Vc)6&j2Qlw)G#?ZYA(bEdpWFJol>y?)g z4X|N0@QBl(K3uQ=jq{67;8UT*O&+pDGnJ7IO1FgHPp#hh0sg=R!DD-*C02eG9EJ;XW1aUl|nqbMJ;6hvDUnq(YNp=F@Is!-L?*FIRw z)7!jLKS*#GqfSqTyXJf;U^Hu#f9Mp7xYXhYE698cNC_DQNaxfafAr|pQcQ#r;K_up z^%Ysd*9LMhKNMgbV<0CAQc}jzqS(XN){dy_5IanV-LsKEmyF$0(4e3a>4f7;hOGlr zmheL&)iRDb9-Jnxu;xzFz4w={ug5DBeFdeYZiYlGU2WPwd~&)@bmeCeL!1gd7FV)t z8EcO)^S$L}STyo_VsJF_PWe0lDgC)0m_etUOAULcOV3Eau6RiVG$_iIdOpyfFV&$s*0$FB#uTQ{7gs% zEW;~Kwvf=gsv)W6nzF3#2X|>SDFwmL`gpVR1QcPH3pais_Tz_e5#T*-anj~MwyaK% z-UbBCs&tXhxcB{W#8W1TQgvSV%b}+&#?KVuK%)*|Y-F!b0pBEY*cLN1i$(LA1u?C1 z2fh_iY@_7}!TTLf=3jYd_UeXiZSNNj1zOX`)A&wHrA_T9gW<3g0K(ZxD$_rHFfp76Pb!ji>__ z{93(u2*wrBvb(gW9rMl%gpMwZ5U zO1G9Nz?g9wecmcd+Xv_SaRuR#C)|Z3h~|p#O66bd*K5Qt`g;EiAFN%bOc0NnMwJZ! zLUq zq*PaiJu50IeuFOOaqiCOQHOae4mqAti{jN#QWQ>sC;Zw{-B(=uIXdU;g`AV>bj$__*N3U~Ds>#XqJ~r61#OltnBw>5&fHPxT9}X1 zq|GOAbC&^m=};qn>$UaFwTx=AJX$_gB=JONt$B1??%G@pEw#q0$y9OoJ!<$u61cc! zKU8AA?F{Z@b)L+wudVSQs%N!#UTZ|J=wsUMfW8t_1-x`_UXHzh13xx3p4WRj+K4AB zDWkI(2|9M^YOlCiFYQ_eXw4ee_P4sdZzW;m=h3sJ3-X)#Ile3Q5|fIs7b432Vx(_J zxKKJZBiWvNjbOez^ev=A>4pDE*VrPSH+R6!>dB+w+2IcL3AERPAmEFL-}K}9Og zr-vawWNR1lgE5DQR^VU#qkt1;@Bv%kg|fR|VN|viwW6x0Ys! zz|r4sNW?jUM14jI0&ayO7W-{?3>xr>{{F&u;xvfQM(B*=EV+?W*itVS)yf3LG1&0n z^)ci@*xrAwgp*(+-~6~8xAH62jAKV7JRg)n3^RSYE-k;Pzz95S7HL4`vv&M?o{hca zj(APn$0FO%aZSvC?d@gzvNq-Zu~v5x+8DfrcN4)vbpo(}f_|m>`*SD5+_@P5khMK) z@23ex>vl~HZA}o1#{^_kwmNu*7HX(97oju4;{}%}Q?aOoU^Yyw_n$bO1x&iu9t>`ytVu3x-9Q0D4sU2Bz6^Vk{5|wGPCkh&n)J`W zi-|dGy1}O%v;5S`qCxu8bzv0+%a!!`IRvyF30=5!jQH1r8y_zpUwcB0k?>N=EZ1>7 zOoxnFZ2I@x95JEZTsl;cpCbmaJI_`4H9Jr2Hdr*wEI2m;XWMOKI_@d;;matq8X-B8 zw`)pIiyN8;!|Qb7$H)2b+u^GAVwokQXwUqGpQ@Q@Zbdv68cN?VXU&s($Le9%fN16^ zEC24QI^MJU!u-9TCA5We6jEp$UCiH4`^3ItyXAOzeM@I7^hvdJZ&vMt(jSl>GZTM^ zhM*PmfVgO>Y=;2&V#Z*8BQmuK$EI2cJc}V!pPWLA~`ap;%kg zfr0?QkCD29$SLGW;nhT~j5dH4!WhdUFUTL~Js@JS6KD2jlCRjL1QddBD^NImax|4l zMoIG_Q;NW?M3Y3FkYhqGl?-#v*(d7FrJ|S%xCuYhWcu%;cIt+cj#qu>sYn~y$rUuC zDh>h$wP@YZ=*XIvCN8Y1e2w%=rrMWBR%v)#Bcofb4>z3_CK`4NDzQp89*q1g&01`&*&kUY(pEVz+)2VD`lX`{L)HqQug^rWBtIc^^)^c+=>}GmQV`+ydlDOeFbSm zx*-I1C^V;(RWLWFp=F36qps;zm?=%D#z9fx`acOJ_iZop=g=NT2Jc1>8rgw=C}CTo zH4zkrgr#2gMmmH6{(2yX9L!Qk>|^;4ms?u<>NMC0>Q0$@cKh1z^etd{qx_`izchijfJYN&7#HKt}ue5qmFmHSjiP7o)HrW^)M(^}I z`-INE^Q_fcf0%)7>F%zxe1T#>Hh5Po$Ff9Y`e{&YXg zV9s+?Macj6t&U6PAOc@n(?8E@s-^%Uxn&obJ|%FgbAVGl;WS%y<^4C9F87EBb&DpW zEN93sIQO#8GvI5P*$aD4@J=BbfhwCJmorrKFY%468(r7Jxu_+3NSU+shE%r_v--c| z$bZp&`J=pSm#wae@*-Ld5EI6Tc0Dx*_0r|Okrpk>vW=GYwWG7A(TGQobkRjRB4b8U zmmcoE1dR;{NggiX*1lT%wdQs|9BzMDXP5*HcpD5|)s~4sEFQfb& zV#hF%bdCnS#R)Q1oZrt6k-+Kw?uFQ9&Ild8H&^FWJdOS1);Zm_3nAJ{R(tSci)0q}ilyYw z>wplq2;yIb>cXLP+Hyr|Xb|Bt)n*ZbK#g%34(>a|vY+Qc=fsSbgzQeJXP*Y^Oc^tT zJi0NYWDB%<&g)yt-_Xm^n##_w)pGs3(vz1u?XD* zJ276ZQ`=N>@tBi+iD(Mu)4xa=1Nb?-DUjLl%-^>#skr7#tQ3)>=&GeE?d7kby5MrP z%Ka2_vzXp0_LaxR_#(YR8Yb8Fa}kdf=(agNw1Xv|0b|bbXGv@Gnw@KH)}NNpRXnk> z)e0MV3JyFr7U_5BTDk}VCRO-Ofl36?Z+TOWof(VMn8AvOi$$oA(wPPPbA@VUr_)u6 zRf^g~og&WBhZY(60LsbQxH0Min4*DjnQ2HK0^(QXB(NhyNpo2-odR<{IOg&jRtNe? z$aR&NeJf$EZQ?^j=yXY{%M<<(+~HqzlGHqFcezNBo-F=3IhR@Rej7iKO3{#ocwD_A z$n^Zg*-l`RJdE*HPP4Rv%zYjs23I^AJUddlFIDYqG&=*!a@%wy)PCFekEiq|&n-Py zo#p^Q!<)jzO>4xuQroCF1pr!JXtV^M>;ps59OqvOCLObt=VLWfHhEg;zIW{F4u-OY z3#!DnIX%r#L6(s{esw|x#nPY$jqK4~d}Zs(r_rIi^=PVvst}O%I!D;H9kw*}0`4^R z%I?a`W=Kj9r>Ec#K{~ZW*5LC>zMvw6V6Hy|_sx>nDQ5n*mXA>-)yt*-V%1qe6zpS z%e_F8U$et}OmcyO_XGn_xl4L`qK>aQsxTSikAAQV1jR&H757s$;ur85;OWI6h@zDC zwPof1k-+IEz{|pn%0W!n!uZO1wL6ylnDo8@FZgVFroO`-05)xzF`ZMRi9AGWdTXP! zK88Z}BJZHDWgVSD?2*&7s}iJBRQ2e#sL9lyuOxReE;&w@FygfNy9vLAzXeQb#Elu0 z_NhE2S(V*_>=JSx2l~)k7SBkeCElD?q9q<^T8?#|P2R78 z)MmY0{O5rn5l#2jKU%ulIttv{TgAGi-4UHNDx>zsp(s28x)nY)zq^|=+dRAiOTnPvCM({sx+Cq%=oBn}e@U*1=( zFS)61P%}r>VI)dHf0r1gYuFi#2|-|;(#96*3Azg&3jSUl(hER>aIoM}?;!Qo&-q=;jSyzLGfWQ+FnFzu~A7H_g%7ELQ;8l+8T%2 zJZ=`IBenfJ4UOpj1uN6j3!=sh921q#qK|_Y{!e;x0i3!ri4B}i@Z)s4!xzuR)s!?NnSi$B}m1v z+T*thR!n4_zy__%-0|F{}(BjbpmQ|OTA_l3)9grz^)Zfo@t^XYgG%Zl(^ z`_rkT5VMm&ntHzfV0BNZmO1r-aF;zPN|@M&x0P^r-|URL+me2UQz@m>!oIJwPxy01 zMz-g2SE^Iz=3qjNK-iwEkVPN0RK8;T4?5E(F%9cBAeJPoP`1Fd&-Or@CQTWa(d2jN zO1c%@+L`)QvLm<@k=W4JE$CyY9lxEy*T_UgGX)a{4?bReeJk`;u`(l9Pe8j7ZBTan z+Ptn5D7ciUk!VxtZknv)B(hE~zf5T>dM~5SEZ?TdZsz9U{L&@qEHp8htFFEA5_2sNUC_)ZXc!&)kdh!Y81 zQjeocZ@W1C0log3Lm(hY9xF_aFnI!g(im(Hs4Tmv;MW*!poKHETXgQ!s8*u1il_@H zN+LD(Pe?M5m5iP%N^14X10;L;$D-P^PTj=~ccsW*>=r?V&tiuIjnNwjJ#z$JKN!

) z_lq^QJEkc{R?GA&7y*&c+W8`Wv%PC%h{N37*xmjBR-ss)QaJ@ZRTWKls$K-nTCF#O zUOYmczd{M54z-*v#nBqFpPoKPF|`uBuf(yXBX4|Rc{*$*#M;VoeOZiBxLK-nK&~DY zwRKm5qB1F?u=&9cDmq9!@HpSV9Z{8t5HZXz!i;%}Z1}nZXBV@mRS@osb%|1M3N*O1 z;$U3(I5S6*7DK={{E|l-8rcbLvdiAxAGQ1nc5?#Lw0q?Wf}`Ro)jd&%>Q>)F#kouw zleeGFvg0ak>cqmXmw_3QrFkKz{kE1YXoY6Q_f-<34NNj!fz;Y`)utkzfKoRBdl0R{AmCCcfs$ zb3P`ZzBv`JQ+h_SMcjqpECu5PC7;@aUmzSI@(QH__)J85XG>|kWQDp>M3I@{4lZa{ zA+LKJ<<=(-Po6HK#O$xim-H#+N$?8ISXIV&56K9~>@L1pb6P5}l{Y=6Sc>))vPpVJ z0ObQdM?w1*2A}$Ga*91r6~nl2_ybFTp=K-mAy0li5YuH}#VP8~{|e4c7~i7{4Ky_j zSWSr-G%9px%lw4I#|Ua3LFxjjdwe|AVw!cF+OTA}zbyK>lyqCNwEa3fioLCzJ(UC7B*p125~}Ks;nG5cw?- z%fv|`mq%3EpXSQ^&o@6c#??4kypQu(IT*xJO1T3nENmtWjR4s_&Dc8*CcrZr!`y`&=S zkJL%nfK|rX$qFvJb2x82lkKa}gZM<)Ti2GF#3MOS{6H`OIAu$4ZsC9q5p8cC;%5GLA@)2El)KJwCmKXYNnamic=aEj)y6;wm$1}}~q zFG7kS#t-Y0xAa~T&!pbH_UPQG_uBAr_fDeL<9Uby{xA;2*5w?1X>LEWbbd1Oek7-l zVX=RJeeNUUpX(^>p@)ht{P6|FJR#7X#9MAZ$Wil6x>WlJ>*8?~`Wtc;O6Oj`Xd>2n zD->59ovKnA%G)WF3kai9=GT9a=_|sbKnp1v9*6_uPvLV^#6}^3MZ0OTQl4K3g4F+jMs%bcw6aA`(j|F=i~Wp6mI$)pm{0sX=7tU#i`$O;L9_JcCobv zjyobbR@iYWiL580%lVmgiDvL=rFF8=^h)AJ#}@I5AA7a+r}V_^*FqV$C#I@hG*wDX z*|>J6kJ2#$e4e3x>a$;%6YR!I$@`Ca!EkPG*o{r>dd(x3g*~jj6c#pzIi8i-R9k-7 zXyj~MFL0)5FcI!??m|5q^w5x$y^S%4I#c(y5w1;}ut|$K-{9>t`^BkZLVvQH+$&Y2m%5WAn=3D=@K9&OG6tA$V&3OcqsIK!(Qx?w|j zf&LZ6yJY8_G0ced3?cO(mA%@VuH_>5gy)|tx54BnEe#VyEcYxI=Tv*8g#RetGPXg31o3=H<|9`S?l^ft2<^5;DxB0)> zw>jZI858?A)BCSFCf0AF_JuAzTG;eTZe4Buq+zp`(gz`rsE0D$e^bquVG|G>rn zyY075;Xm7DWc&6I{JW0zA58gwxBWI8d^<<}m3>0PS3#3Y|O%g g|Nmd|Kg7GElfHw~|J;^LjI8XeP$VS6vLaCb2SB~|TL1t6 literal 0 HcmV?d00001 diff --git a/cognee/modules/data/processing/filter_affected_chunks.py b/cognee/modules/data/processing/filter_affected_chunks.py new file mode 100644 index 000000000..599d16ebf --- /dev/null +++ b/cognee/modules/data/processing/filter_affected_chunks.py @@ -0,0 +1,25 @@ +from cognee.infrastructure.databases.vector import get_vector_engine +from .chunk_types import DocumentChunk + +async def filter_affected_chunks(data_chunks: list[DocumentChunk], collection_name: str) -> list[DocumentChunk]: + vector_engine = get_vector_engine() + + if not await vector_engine.has_collection(collection_name): + # If collection doesn't exist, all data_chunks are new + return data_chunks + + existing_chunks = await vector_engine.retrieve( + collection_name, + [str(chunk.chunk_id) for chunk in data_chunks], + ) + + existing_chunks_map = {chunk.id: chunk.payload for chunk in existing_chunks} + + affected_data_chunks = [] + + for chunk in data_chunks: + if chunk.chunk_id not in existing_chunks_map or \ + chunk.text != existing_chunks_map[chunk.chunk_id]["text"]: + affected_data_chunks.append(chunk) + + return affected_data_chunks diff --git a/cognee/modules/data/processing/has_new_chunks.py b/cognee/modules/data/processing/has_new_chunks.py new file mode 100644 index 000000000..dc3ca3c20 --- /dev/null +++ b/cognee/modules/data/processing/has_new_chunks.py @@ -0,0 +1,30 @@ +from cognee.infrastructure.databases.vector import get_vector_engine +from .chunk_types import DocumentChunk + +async def has_new_chunks(data_chunks: list[DocumentChunk], collection_name: str) -> list[DocumentChunk]: + vector_engine = get_vector_engine() + + if not await vector_engine.has_collection(collection_name): + # There is no collection created, + # so no existing chunks, all chunks are new. + return True + + existing_chunks = await vector_engine.retrieve( + collection_name, + [str(chunk.chunk_id) for chunk in data_chunks], + ) + + if len(existing_chunks) == 0: + # If we don't find any existing chunk, + # all chunks are new. + return True + + existing_chunks_map = {chunk.id: chunk.payload for chunk in existing_chunks} + + new_data_chunks = [ + chunk for chunk in data_chunks \ + if chunk.chunk_id not in existing_chunks_map \ + or chunk.text != existing_chunks_map[chunk.chunk_id]["text"] + ] + + return len(new_data_chunks) > 0 diff --git a/cognee/modules/data/processing/process_documents.py b/cognee/modules/data/processing/process_documents.py new file mode 100644 index 000000000..1eb3bbd3e --- /dev/null +++ b/cognee/modules/data/processing/process_documents.py @@ -0,0 +1,41 @@ +from cognee.infrastructure.databases.graph import get_graph_engine +from .document_types import Document + +async def process_documents(documents: list[Document], parent_node_id: str = None): + graph_engine = await get_graph_engine() + + nodes = [] + edges = [] + + if parent_node_id and await graph_engine.extract_node(parent_node_id) is None: + nodes.append((parent_node_id, {})) + + document_nodes = await graph_engine.extract_nodes([str(document.id) for document in documents]) + + for (document_index, document) in enumerate(documents): + document_node = document_nodes[document_index] if document_index in document_nodes else None + + if document_node is None: + nodes.append((str(document.id), document.to_dict())) + + if parent_node_id: + edges.append(( + parent_node_id, + str(document.id), + "has_document", + dict( + relationship_name = "has_document", + source_node_id = parent_node_id, + target_node_id = str(document.id), + ), + )) + + if len(nodes) > 0: + await graph_engine.add_nodes(nodes) + await graph_engine.add_edges(edges) + + for document in documents: + document_reader = document.get_reader() + + for document_chunk in document_reader.read(max_chunk_size = 1024): + yield document_chunk diff --git a/cognee/modules/data/processing/remove_obsolete_chunks.py b/cognee/modules/data/processing/remove_obsolete_chunks.py new file mode 100644 index 000000000..1bc70a394 --- /dev/null +++ b/cognee/modules/data/processing/remove_obsolete_chunks.py @@ -0,0 +1,29 @@ + +from cognee.infrastructure.databases.graph import get_graph_engine +# from cognee.infrastructure.databases.vector import get_vector_engine +from .chunk_types import DocumentChunk + +async def remove_obsolete_chunks(data_chunks: list[DocumentChunk]) -> list[DocumentChunk]: + graph_engine = await get_graph_engine() + + document_ids = set((data_chunk.document_id for data_chunk in data_chunks)) + + obsolete_chunk_ids = [] + + for document_id in document_ids: + chunk_ids = await graph_engine.get_successor_ids(document_id, edge_label = "has_chunk") + + for chunk_id in chunk_ids: + previous_chunks = await graph_engine.get_predecessor_ids(chunk_id, edge_label = "next_chunk") + + if len(previous_chunks) == 0: + obsolete_chunk_ids.append(chunk_id) + + if len(obsolete_chunk_ids) > 0: + await graph_engine.delete_nodes(obsolete_chunk_ids) + + disconnected_nodes = await graph_engine.get_disconnected_nodes() + if len(disconnected_nodes) > 0: + await graph_engine.delete_nodes(disconnected_nodes) + + return data_chunks diff --git a/cognee/modules/ingestion/classify.py b/cognee/modules/ingestion/classify.py index 69d20ba64..d0c3ca0aa 100644 --- a/cognee/modules/ingestion/classify.py +++ b/cognee/modules/ingestion/classify.py @@ -8,7 +8,7 @@ def classify(data: Union[str, BinaryIO], filename: str = None): return TextData(data) if isinstance(data, BufferedReader): - return BinaryData(data) + return BinaryData(data, data.name.split("/")[-1] if data.name else filename) if hasattr(data, "file"): return BinaryData(data.file, filename) diff --git a/cognee/modules/ingestion/data_types/BinaryData.py b/cognee/modules/ingestion/data_types/BinaryData.py index 59a590635..5531fec86 100644 --- a/cognee/modules/ingestion/data_types/BinaryData.py +++ b/cognee/modules/ingestion/data_types/BinaryData.py @@ -17,7 +17,7 @@ class BinaryData(IngestionData): def get_identifier(self): metadata = self.get_metadata() - return metadata["mime_type"] + "_" + "|".join(metadata["keywords"]) + return self.name + "_" + metadata["mime_type"] def get_metadata(self): self.ensure_metadata() diff --git a/cognee/modules/ingestion/data_types/TextData.py b/cognee/modules/ingestion/data_types/TextData.py index e04376051..9f10b0d54 100644 --- a/cognee/modules/ingestion/data_types/TextData.py +++ b/cognee/modules/ingestion/data_types/TextData.py @@ -13,7 +13,7 @@ class TextData(IngestionData): self.data = data def get_identifier(self): - keywords = self.get_metadata()["keywords"] + keywords = extract_keywords(self.data) return "text/plain" + "_" + "|".join(keywords) @@ -24,7 +24,7 @@ class TextData(IngestionData): def ensure_metadata(self): if self.metadata is None: - self.metadata = dict(keywords = extract_keywords(self.data)) + self.metadata = {} def get_data(self): return self.data diff --git a/cognee/modules/ingestion/save_data_to_file.py b/cognee/modules/ingestion/save_data_to_file.py index 162d858fc..1bbfaec37 100644 --- a/cognee/modules/ingestion/save_data_to_file.py +++ b/cognee/modules/ingestion/save_data_to_file.py @@ -17,8 +17,8 @@ def save_data_to_file(data: Union[str, BinaryIO], dataset_name: str, filename: s file_metadata = classified_data.get_metadata() if "name" not in file_metadata or file_metadata["name"] is None: letters = string.ascii_lowercase - random_string = ''.join(random.choice(letters) for _ in range(32)) - file_metadata["name"] = "file" + random_string + random_string = "".join(random.choice(letters) for _ in range(32)) + file_metadata["name"] = "text_" + random_string + ".txt" file_name = file_metadata["name"] LocalStorage(storage_path).store(file_name, classified_data.get_data()) diff --git a/cognee/modules/pipelines/Pipeline.py b/cognee/modules/pipelines/Pipeline.py new file mode 100644 index 000000000..13807d9ed --- /dev/null +++ b/cognee/modules/pipelines/Pipeline.py @@ -0,0 +1,18 @@ +from uuid import UUID, uuid4 +from typing import Optional +from pydantic import BaseModel +from .models.Task import Task + +class PipelineConfig(BaseModel): + batch_count: int = 10 + description: Optional[str] + +class Pipeline(): + id: UUID = uuid4() + name: str + description: str + tasks: list[Task] = [] + + def __init__(self, name: str, pipeline_config: PipelineConfig): + self.name = name + self.description = pipeline_config.description diff --git a/cognee/modules/pipelines/__init__.py b/cognee/modules/pipelines/__init__.py new file mode 100644 index 000000000..cba929c36 --- /dev/null +++ b/cognee/modules/pipelines/__init__.py @@ -0,0 +1,2 @@ +from .operations.run_tasks import run_tasks +from .operations.run_parallel import run_tasks_parallel diff --git a/cognee/modules/pipelines/models/Pipeline.py b/cognee/modules/pipelines/models/Pipeline.py new file mode 100644 index 000000000..7666b8bbf --- /dev/null +++ b/cognee/modules/pipelines/models/Pipeline.py @@ -0,0 +1,22 @@ +from typing import List +from uuid import uuid4 +from datetime import datetime, timezone +from sqlalchemy import Column, UUID, DateTime, String, Text +from sqlalchemy.orm import relationship, Mapped +from cognee.infrastructure.databases.relational import ModelBase +from .PipelineTask import PipelineTask + +class Pipeline(ModelBase): + __tablename__ = "pipelines" + + id = Column(UUID, primary_key = True, default = uuid4()) + name = Column(String) + description = Column(Text, nullable = True) + + created_at = Column(DateTime, default = datetime.now(timezone.utc)) + updated_at = Column(DateTime, onupdate = datetime.now(timezone.utc)) + + tasks = Mapped[List["Task"]] = relationship( + secondary = PipelineTask.__tablename__, + back_populates = "pipeline", + ) diff --git a/cognee/modules/pipelines/models/PipelineTask.py b/cognee/modules/pipelines/models/PipelineTask.py new file mode 100644 index 000000000..82b618368 --- /dev/null +++ b/cognee/modules/pipelines/models/PipelineTask.py @@ -0,0 +1,14 @@ +from uuid import uuid4 +from datetime import datetime, timezone +from sqlalchemy import Column, DateTime, UUID, ForeignKey +from cognee.infrastructure.databases.relational import ModelBase + +class PipelineTask(ModelBase): + __tablename__ = "pipeline_task" + + id = Column(UUID, primary_key = True, default = uuid4()) + + created_at = Column(DateTime, default = datetime.now(timezone.utc)) + + pipeline_id = Column("pipeline", UUID, ForeignKey("pipeline.id"), primary_key = True) + task_id = Column("task", UUID, ForeignKey("task.id"), primary_key = True) diff --git a/cognee/modules/pipelines/models/Task.py b/cognee/modules/pipelines/models/Task.py new file mode 100644 index 000000000..34a193dc7 --- /dev/null +++ b/cognee/modules/pipelines/models/Task.py @@ -0,0 +1,24 @@ +from uuid import uuid4 +from typing import List +from datetime import datetime, timezone +from sqlalchemy.orm import relationship, Mapped +from sqlalchemy import Column, String, DateTime, UUID, Text +from cognee.infrastructure.databases.relational import ModelBase +from .PipelineTask import PipelineTask + +class Task(ModelBase): + __tablename__ = "tasks" + + id = Column(UUID, primary_key = True, default = uuid4()) + name = Column(String) + description = Column(Text, nullable = True) + + executable = Column(Text) + + created_at = Column(DateTime, default = datetime.now(timezone.utc)) + updated_at = Column(DateTime, onupdate = datetime.now(timezone.utc)) + + datasets: Mapped[List["Pipeline"]] = relationship( + secondary = PipelineTask.__tablename__, + back_populates = "task" + ) diff --git a/cognee/modules/pipelines/operations/__init__.py b/cognee/modules/pipelines/operations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/cognee/modules/pipelines/operations/__tests__/__index__.py b/cognee/modules/pipelines/operations/__tests__/__index__.py new file mode 100644 index 000000000..e69de29bb diff --git a/cognee/modules/pipelines/operations/__tests__/artificial-inteligence.v1.pdf b/cognee/modules/pipelines/operations/__tests__/artificial-inteligence.v1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7de338b8cfe5ec9120e1fb0b4a8d5dbc541b52ca GIT binary patch literal 29616 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 z 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 literal 0 HcmV?d00001 diff --git a/cognee/modules/pipelines/operations/__tests__/artificial-inteligence.v2.pdf b/cognee/modules/pipelines/operations/__tests__/artificial-inteligence.v2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..601c6297da4f44d7f75fb4b8a59c5673b5fc8fff GIT binary patch literal 55375 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

@}vN+ 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 Callable[[Any], Generator[Any, Any, Any]]: + async def parallel_run(*args, **kwargs): + parallel_tasks = [asyncio.create_task(task.run(*args, **kwargs)) for task in tasks] + + results = await asyncio.gather(*parallel_tasks) + return results[len(results) - 1] if len(results) > 1 else [] + + return Task(parallel_run) diff --git a/cognee/modules/pipelines/operations/run_tasks.py b/cognee/modules/pipelines/operations/run_tasks.py new file mode 100644 index 000000000..1000743da --- /dev/null +++ b/cognee/modules/pipelines/operations/run_tasks.py @@ -0,0 +1,90 @@ +import inspect +import logging +from ..tasks.Task import Task + +logger = logging.getLogger("run_tasks(tasks: [Task], data)") + +async def run_tasks(tasks: [Task], data): + if len(tasks) == 0: + yield data + return + + running_task = tasks[0] + batch_size = running_task.task_config["batch_size"] + leftover_tasks = tasks[1:] + next_task = leftover_tasks[0] if len(leftover_tasks) > 1 else None + # next_task_batch_size = next_task.task_config["batch_size"] if next_task else 1 + + if inspect.isasyncgenfunction(running_task.executable): + logger.info(f"Running async generator task: `{running_task.executable.__name__}`") + try: + results = [] + + async_iterator = running_task.run(data) + + async for partial_result in async_iterator: + results.append(partial_result) + + if len(results) == batch_size: + async for result in run_tasks(leftover_tasks, results[0] if batch_size == 1 else results): + yield result + + results = [] + + if len(results) > 0: + async for result in run_tasks(leftover_tasks, results): + yield result + + results = [] + + logger.info(f"Finished async generator task: `{running_task.executable.__name__}`") + except Exception as error: + logger.error( + "Error occurred while running async generator task: `%s`\n%s\n", + running_task.executable.__name__, + str(error), + exc_info = True, + ) + raise error + + elif inspect.isgeneratorfunction(running_task.executable): + logger.info(f"Running generator task: `{running_task.executable.__name__}`") + try: + results = [] + + for partial_result in running_task.run(data): + results.append(partial_result) + + if len(results) == batch_size: + async for result in run_tasks(leftover_tasks, results[0] if batch_size == 1 else results): + yield result + + results = [] + + if len(results) > 0: + async for result in run_tasks(leftover_tasks, results): + yield result + + results = [] + + logger.info(f"Running generator task: `{running_task.executable.__name__}`") + except Exception as error: + logger.error( + "Error occurred while running generator task: `%s`\n%s\n", + running_task.executable.__name__, + str(error), + exc_info = True, + ) + raise error + + elif inspect.iscoroutinefunction(running_task.executable): + task_result = await running_task.run(data) + + async for result in run_tasks(leftover_tasks, task_result): + yield result + + elif inspect.isfunction(running_task.executable): + task_result = running_task.run(data) + + async for result in run_tasks(leftover_tasks, task_result): + yield result diff --git a/cognee/modules/pipelines/tasks/Task.py b/cognee/modules/pipelines/tasks/Task.py new file mode 100644 index 000000000..8f3c510cb --- /dev/null +++ b/cognee/modules/pipelines/tasks/Task.py @@ -0,0 +1,32 @@ +from typing import Union, Callable, Any, Coroutine, Generator, AsyncGenerator + +class Task(): + executable: Union[ + Callable[..., Any], + Callable[..., Coroutine[Any, Any, Any]], + Generator[Any, Any, Any], + AsyncGenerator[Any, Any], + ] + task_config: dict[str, Any] = { + "batch_size": 1, + } + default_params: dict[str, Any] = {} + + def __init__(self, executable, *args, task_config = None, **kwargs): + self.executable = executable + self.default_params = { + "args": args, + "kwargs": kwargs + } + + if task_config is not None: + self.task_config = task_config + + if "batch_size" not in task_config: + self.task_config["batch_size"] = 1 + + def run(self, *args, **kwargs): + combined_args = self.default_params["args"] + args + combined_kwargs = { **self.default_params["kwargs"], **kwargs } + + return self.executable(*combined_args, **combined_kwargs) diff --git a/cognee/modules/search/graph/search_adjacent.py b/cognee/modules/search/graph/search_adjacent.py index efc50afb2..a8eb82355 100644 --- a/cognee/modules/search/graph/search_adjacent.py +++ b/cognee/modules/search/graph/search_adjacent.py @@ -1,15 +1,11 @@ -""" This module contains the function to find the neighbours of a given node in the graph""" - - from typing import Union, Dict import networkx as nx -from cognee.shared.data_models import GraphDBType -from cognee.infrastructure.databases.graph.config import get_graph_config +from cognee.infrastructure.databases.graph import get_graph_engine +from cognee.infrastructure.databases.vector import get_vector_engine async def search_adjacent(graph: Union[nx.Graph, any], query: str, other_param: dict = None) -> Dict[str, str]: """ - Find the neighbours of a given node in the graph and return their descriptions. - Supports both NetworkX graphs and Neo4j graph databases based on the configuration. + Find the neighbours of a given node in the graph and return their ids and descriptions. Parameters: - graph (Union[nx.Graph, AsyncSession]): The graph object or Neo4j session. @@ -19,29 +15,24 @@ async def search_adjacent(graph: Union[nx.Graph, any], query: str, other_param: Returns: - Dict[str, str]: A dictionary containing the unique identifiers and descriptions of the neighbours of the given node. """ - node_id = other_param.get('node_id') if other_param else query + node_id = other_param.get("node_id") if other_param else query if node_id is None: return {} - graph_config = get_graph_config() - - if graph_config.graph_database_provider == "NETWORKX": - if node_id not in graph: - return {} - - neighbors = list(graph.neighbors(node_id)) - neighbor_descriptions = {neighbor: graph.nodes[neighbor].get('description') for neighbor in neighbors} - return neighbor_descriptions - - elif graph_config.graph_database_provider == "neo4j": - cypher_query = """ - MATCH (node {id: $node_id})-[:CONNECTED_TO]->(neighbor) - RETURN neighbor.id AS neighbor_id, neighbor.description AS description - """ - results = await graph.run(cypher_query, node_id=node_id) - neighbor_descriptions = {record["neighbor_id"]: record["description"] for record in await results.list() if "description" in record} - return neighbor_descriptions + graph_engine = await get_graph_engine() + exact_node = await graph_engine.extract_node(node_id) + if exact_node is not None and "id" in exact_node: + neighbours = await graph_engine.get_neighbours(exact_node["id"]) else: - raise ValueError("Unsupported graph engine type in the configuration.") \ No newline at end of file + vector_engine = get_vector_engine() + collection_name = "classification" + data_points = await vector_engine.search(collection_name, query_text = node_id, limit = 5) + + if len(data_points) == 0: + return [] + + neighbours = await graph_engine.get_neighbours(data_points[0].id) + + return [node["name"] for node in neighbours] diff --git a/cognee/modules/search/graph/search_categories.py b/cognee/modules/search/graph/search_categories.py deleted file mode 100644 index 9a07419bc..000000000 --- a/cognee/modules/search/graph/search_categories.py +++ /dev/null @@ -1,65 +0,0 @@ -""" Search categories in the graph and return their summary attributes. """ -from typing import Union -import re -import networkx as nx -from pydantic import BaseModel -from cognee.shared.data_models import GraphDBType -from cognee.modules.search.llm.extraction.categorize_relevant_category import categorize_relevant_category -from cognee.infrastructure.databases.graph.config import get_graph_config - -def strip_exact_regex(s, substring): - # Escaping substring to be used in a regex pattern - pattern = re.escape(substring) - # Regex to match the exact substring at the start and end - return re.sub(f"^{pattern}|{pattern}$", "", s) - - -class DefaultResponseModel(BaseModel): - document_id: str - -async def search_categories(query:str, graph: Union[nx.Graph, any], query_label: str=None): - """ - Filter nodes in the graph that contain the specified label and return their summary attributes. - This function supports both NetworkX graphs and Neo4j graph databases. - - Parameters: - - graph (Union[nx.Graph, AsyncSession]): The graph object or Neo4j session. - - query_label (str): The label to filter nodes by. - - Returns: - - Union[Dict, List[Dict]]: For NetworkX, returns a dictionary where keys are node identifiers, - and values are their 'content_labels' attributes. For Neo4j, returns a list of dictionaries, - each representing a node with 'nodeId' and 'summary'. - """ - # Determine which client is in use based on the configuration - graph_config = get_graph_config() - - if graph_config.graph_database_provider == "NETWORKX": - - categories_and_ids = [ - {"document_id": strip_exact_regex(_, "DATA_SUMMARY__"), "Summary": data["summary"]} - for _, data in graph.nodes(data=True) - if "summary" in data - ] - connected_nodes = [] - for id in categories_and_ids: - print("id", id) - connected_nodes.append(list(graph.neighbors(id["document_id"]))) - check_relevant_category = await categorize_relevant_category(query, categories_and_ids, response_model=DefaultResponseModel ) - connected_nodes = list(graph.neighbors(check_relevant_category["document_id"])) - descriptions = {node: graph.nodes[node].get("description", "No desc available") for node in connected_nodes} - return descriptions - - elif graph_config.graph_database_provider == "neo4j": - # Logic for Neo4j - cypher_query = """ - MATCH (n) - WHERE $label IN labels(n) AND EXISTS(n.summary) - RETURN id(n) AS nodeId, n.summary AS summary - """ - result = await graph.run(cypher_query, label=query_label) - nodes_summary = [{"nodeId": record["nodeId"], "summary": record["summary"]} for record in await result.list()] - return nodes_summary - - else: - raise ValueError("Unsupported graph engine type.") diff --git a/cognee/modules/search/graph/search_neighbour.py b/cognee/modules/search/graph/search_neighbour.py deleted file mode 100644 index 6f198a6d8..000000000 --- a/cognee/modules/search/graph/search_neighbour.py +++ /dev/null @@ -1,74 +0,0 @@ -""" Fetches the context of a given node in the graph""" -import networkx as nx -from typing import Union -from cognee.shared.data_models import GraphDBType -from cognee.infrastructure.databases.graph.config import get_graph_config - -async def search_neighbour(graph: Union[nx.Graph, any], query: str, - other_param: dict = None): - """ - Search for nodes that share the same 'layer_uuid' as the specified node and return their descriptions. - Adapts to both NetworkX graphs and Neo4j graph databases based on the configuration. - - Parameters: - - graph (Union[nx.Graph, AsyncSession]): The graph object or Neo4j session. - - id (str): The identifier of the node to match against. - - other_param (dict, optional): A dictionary that may contain 'node_id' to specify the node. - - Returns: - - List[str]: A list of 'description' attributes of nodes that share the same 'layer_uuid' with the specified node. - """ - node_id = other_param.get('node_id') if other_param else query - - if node_id is None: - return [] - - graph_config = get_graph_config() - - if graph_config.graph_database_provider == "NETWORKX": - relevant_context = [] - target_layer_uuid = graph.nodes[node_id].get("layer_uuid") - - for n, attr in graph.nodes(data=True): - if attr.get("layer_uuid") == target_layer_uuid and "description" in attr: - relevant_context.append(attr["description"]) - - return relevant_context - - - elif graph_config.graph_database_provider == "neo4j": - from neo4j import AsyncSession - - if isinstance(graph, AsyncSession): - cypher_query = """ - MATCH (target {id: $node_id}) - WITH target.layer_uuid AS layer - MATCH (n) - WHERE n.layer_uuid = layer AND EXISTS(n.description) - RETURN n.description AS description - """ - result = await graph.run(cypher_query, node_id=node_id) - descriptions = [record["description"] for record in await result.list()] - - return descriptions - else: - raise ValueError("Graph session does not match the specified graph engine type in the configuration.") - - else: - raise ValueError("Unsupported graph engine type in the configuration.") - - - -# if __name__ == '__main__': -# import asyncio -# async def main(): -# from cognee.shared.data_models import GraphDBType -# -# graph_client = get_graph_client(GraphDBType.NETWORKX) -# graph = await graph_client.graph -# -# await fetch_context(graph, "1") -# -# asyncio.run(main()) - - diff --git a/cognee/modules/search/graph/search_similarity.py b/cognee/modules/search/graph/search_similarity.py new file mode 100644 index 000000000..d06bc897e --- /dev/null +++ b/cognee/modules/search/graph/search_similarity.py @@ -0,0 +1,22 @@ +from typing import Union, Dict +import networkx as nx +from cognee.infrastructure.databases.vector import get_vector_engine + +async def search_similarity(query: str, graph: Union[nx.Graph, any]) -> Dict[str, str]: + """ + Parameters: + - graph (Union[nx.Graph, AsyncSession]): The graph object or Neo4j session. + - query (str): The query string to filter nodes by, e.g., 'SUMMARY'. + + Returns: + - Dict[str, str]: A dictionary where keys are node identifiers containing the query string, and values are their 'result' attributes. + """ + vector_engine = get_vector_engine() + + similar_results = await vector_engine.search("chunks", query, limit = 5) + results = [{ + "text": result.payload["text"], + "chunk_id": result.payload["chunk_id"], + } for result in similar_results] + + return results diff --git a/cognee/modules/search/graph/search_summary.py b/cognee/modules/search/graph/search_summary.py index af0d6c24c..a46e35968 100644 --- a/cognee/modules/search/graph/search_summary.py +++ b/cognee/modules/search/graph/search_summary.py @@ -1,21 +1,10 @@ -import re from typing import Union, Dict import networkx as nx -from cognee.modules.search.llm.extraction.categorize_relevant_summary import categorize_relevant_summary -from cognee.shared.data_models import GraphDBType, ResponseSummaryModel -from cognee.infrastructure.databases.graph.config import get_graph_config +from cognee.shared.data_models import ChunkSummaries +from cognee.infrastructure.databases.vector import get_vector_engine -def strip_exact_regex(s, substring): - # Escaping substring to be used in a regex pattern - pattern = re.escape(substring) - # Regex to match the exact substring at the start and end - return re.sub(f"^{pattern}|{pattern}$", "", s) - -async def search_summary( query: str, graph: Union[nx.Graph, any]) -> Dict[str, str]: +async def search_summary(query: str, graph: Union[nx.Graph, any]) -> Dict[str, str]: """ - Filter nodes based on a condition (such as containing 'SUMMARY' in their identifiers) and return their summary attributes. - Supports both NetworkX graphs and Neo4j graph databases based on the configuration. - Parameters: - graph (Union[nx.Graph, AsyncSession]): The graph object or Neo4j session. - query (str): The query string to filter nodes by, e.g., 'SUMMARY'. @@ -24,34 +13,12 @@ async def search_summary( query: str, graph: Union[nx.Graph, any]) -> Dict[str, Returns: - Dict[str, str]: A dictionary where keys are node identifiers containing the query string, and values are their 'summary' attributes. """ - graph_config = get_graph_config() + vector_engine = get_vector_engine() - if graph_config.graph_database_provider == "NETWORKX": - summaries_and_ids = [ - {"document_id": strip_exact_regex(_, "DATA_SUMMARY__"), "Summary": data["summary"]} - for _, data in graph.nodes(data=True) - if "summary" in data - ] - print("summaries_and_ids", summaries_and_ids) - check_relevant_summary = await categorize_relevant_summary(query, summaries_and_ids, response_model=ResponseSummaryModel) - print("check_relevant_summary", check_relevant_summary) + summaries_results = await vector_engine.search("chunk_summaries", query, limit = 5) + summaries = [{ + "text": summary.payload["text"], + "chunk_id": summary.payload["chunk_id"], + } for summary in summaries_results] - connected_nodes = list(graph.neighbors(check_relevant_summary['document_id'])) - print("connected_nodes", connected_nodes) - descriptions = {node: graph.nodes[node].get('description', 'No desc available') for node in connected_nodes} - print("descs", descriptions) - return descriptions - - - elif graph_config.graph_database_provider == "neo4j": - cypher_query = f""" - MATCH (n) - WHERE n.id CONTAINS $query AND EXISTS(n.summary) - RETURN n.id AS nodeId, n.summary AS summary - """ - results = await graph.run(cypher_query, query=query) - summary_data = {record["nodeId"]: record["summary"] for record in await results.list()} - return summary_data - - else: - raise ValueError("Unsupported graph engine type in the configuration.") + return summaries diff --git a/cognee/modules/search/llm/extraction/categorize_relevant_summary.py b/cognee/modules/search/llm/extraction/categorize_relevant_summary.py index 2d6be6790..1ed09e69c 100644 --- a/cognee/modules/search/llm/extraction/categorize_relevant_summary.py +++ b/cognee/modules/search/llm/extraction/categorize_relevant_summary.py @@ -3,15 +3,13 @@ from pydantic import BaseModel from cognee.infrastructure.llm.prompts import render_prompt from cognee.infrastructure.llm.get_llm_client import get_llm_client -async def categorize_relevant_summary(query: str, summary, response_model: Type[BaseModel]): +async def categorize_relevant_summary(query: str, summaries, response_model: Type[BaseModel]): llm_client = get_llm_client() - enriched_query= render_prompt("categorize_summary.txt", {"query": query, "summaries": summary}) + enriched_query= render_prompt("categorize_summary.txt", {"query": query, "summaries": summaries}) - print("enriched_query", enriched_query) - - system_prompt = " Choose the relevant summary and return appropriate output based on the model" + system_prompt = "Choose the relevant summaries and return appropriate output based on the model" llm_output = await llm_client.acreate_structured_output(enriched_query, system_prompt, response_model) - return llm_output.model_dump() + return llm_output diff --git a/cognee/modules/search/vector/search_similarity.py b/cognee/modules/search/vector/search_similarity.py deleted file mode 100644 index be1016dca..000000000 --- a/cognee/modules/search/vector/search_similarity.py +++ /dev/null @@ -1,59 +0,0 @@ -from cognee.infrastructure.databases.graph.get_graph_client import get_graph_client -from cognee.infrastructure.databases.vector import get_vector_engine - -async def search_similarity(query: str, graph): # graph must be there in order to be compatible with generic call - # graph_config = get_graph_config() - # - # graph_db_type = graph_config.graph_engine - - graph_client = await get_graph_client() - - layer_nodes = await graph_client.get_layer_nodes() - - unique_layer_uuids = set(node["layer_id"] for node in layer_nodes) - print("unique_layer_uuids", unique_layer_uuids) - - - graph_nodes = [] - - for layer_id in unique_layer_uuids: - vector_engine = get_vector_engine() - - results = await vector_engine.search(layer_id, query_text = query, limit = 10) - - if len(results) > 0: - graph_nodes.extend([ - dict( - layer_id = result.payload["references"]["cognitive_layer"], - node_id = result.payload["references"]["node_id"], - score = result.score, - ) for result in results if result.score > 0.3 - ]) - - if len(graph_nodes) == 0: - return [] - - - return graph_nodes - - - - # for graph_node_data in graph_nodes: - # if graph_node_data['score'] >0.8: - # graph_node = await graph_client.extract_node(graph_node_data["node_id"]) - # - # if "chunk_collection" not in graph_node and "chunk_id" not in graph_node: - # continue - # - # vector_point = await vector_engine.retrieve( - # graph_node["chunk_collection"], - # graph_node["chunk_id"], - # ) - # - # print("vector_point", vector_point.payload["text"]) - # - # relevant_context.append(vector_point.payload["text"]) - # - # print(relevant_context) - # - # return deduplicate(relevant_context) diff --git a/cognee/modules/search/vector/search_traverse.py b/cognee/modules/search/vector/search_traverse.py new file mode 100644 index 000000000..4d64771f2 --- /dev/null +++ b/cognee/modules/search/vector/search_traverse.py @@ -0,0 +1,21 @@ +from cognee.infrastructure.databases.graph.get_graph_engine import get_graph_engine +from cognee.infrastructure.databases.vector import get_vector_engine + +async def search_traverse(query: str, graph): # graph must be there in order to be compatible with generic call + graph_engine = await get_graph_engine() + vector_engine = get_vector_engine() + + results = await vector_engine.search("classification", query_text = query, limit = 10) + + rules = [] + + if len(results) > 0: + for result in results: + graph_node_id = result.id + + edges = await graph_engine.get_edges(graph_node_id) + + for edge in edges: + rules.append(f"{edge[0]} {edge[2]['relationship_name']} {edge[1]}") + + return rules diff --git a/cognee/modules/topology/topology.py b/cognee/modules/topology/topology.py index cac72a660..c733763c2 100644 --- a/cognee/modules/topology/topology.py +++ b/cognee/modules/topology/topology.py @@ -4,22 +4,23 @@ import csv import json import logging import os +from typing import Any, Dict, List, Optional, Union, Type +import asyncio import aiofiles import pandas as pd -from pydantic import BaseModel, Field -from typing import Any, Dict, List, Optional, Union, Type +from pydantic import BaseModel from cognee.infrastructure.data.chunking.config import get_chunk_config from cognee.infrastructure.data.chunking.get_chunking_engine import get_chunk_engine -from cognee.infrastructure.databases.graph.get_graph_client import get_graph_client +from cognee.infrastructure.databases.graph.get_graph_engine import get_graph_engine from cognee.infrastructure.databases.relational import get_relationaldb_config from cognee.infrastructure.files.utils.extract_text_from_file import extract_text_from_file from cognee.infrastructure.files.utils.guess_file_type import guess_file_type, FileTypeException from cognee.modules.cognify.config import get_cognify_config from cognee.base_config import get_base_config -from cognee.modules.topology.topology_data_models import NodeModel, RelationshipModel, Document, DirectoryModel, DirMetadata, GitHubRepositoryModel -import asyncio +from cognee.modules.topology.topology_data_models import NodeModel + cognify_config = get_cognify_config() base_config = get_base_config() @@ -59,12 +60,12 @@ class TopologyEngine: async def load_data(self, file_path: str) -> Union[List[Dict[str, Any]], Dict[str, Any]]: """Load data from a JSON or CSV file.""" try: - if file_path.endswith('.json'): - async with aiofiles.open(file_path, mode='r') as f: + if file_path.endswith(".json"): + async with aiofiles.open(file_path, mode="r") as f: data = await f.read() return json.loads(data) - elif file_path.endswith('.csv'): - async with aiofiles.open(file_path, mode='r') as f: + elif file_path.endswith(".csv"): + async with aiofiles.open(file_path, mode="r") as f: content = await f.read() reader = csv.DictReader(content.splitlines()) return list(reader) @@ -73,7 +74,7 @@ class TopologyEngine: except Exception as e: raise RuntimeError(f"Failed to load data from {file_path}: {e}") - async def add_graph_topology(self, file_path: str=None, dataset_files: list[tuple[Any, Any]]=None,): + async def add_graph_topology(self, file_path: str = None, files: list = None): """Add graph topology from a JSON or CSV file.""" if self.infer: from cognee.modules.topology.infer_data_topology import infer_data_topology @@ -84,48 +85,43 @@ class TopologyEngine: chunk_engine = get_chunk_engine() chunk_strategy = chunk_config.chunk_strategy + for base_file in files: + with open(base_file["file_path"], "rb") as file: + try: + file_type = guess_file_type(file) + text = extract_text_from_file(file, file_type) + subchunks, chunks_with_ids = chunk_engine.chunk_data(chunk_strategy, text, chunk_config.chunk_size, + chunk_config.chunk_overlap) - for dataset_name, files in dataset_files: - for base_file in files: - with open(base_file["file_path"], "rb") as file: - try: - file_type = guess_file_type(file) - text = extract_text_from_file(file, file_type) + if chunks_with_ids[0][0] == 1: + initial_chunks_and_ids.append({base_file["id"]: chunks_with_ids}) - subchunks, chunks_with_ids = chunk_engine.chunk_data(chunk_strategy, text, chunk_config.chunk_size, - chunk_config.chunk_overlap) - - if chunks_with_ids[0][0] == 1: - initial_chunks_and_ids.append({base_file['id']: chunks_with_ids}) - - except FileTypeException: - logger.warning("File (%s) has an unknown file type. We are skipping it.", file["id"]) + except FileTypeException: + logger.warning("File (%s) has an unknown file type. We are skipping it.", file["id"]) topology = await infer_data_topology(str(initial_chunks_and_ids)) - graph_client = await get_graph_client() - - for node in topology["nodes"]: - await graph_client.add_node(node["id"], node) - for edge in topology["edges"]: - await graph_client.add_edge(edge["source_node_id"], edge["target_node_id"], relationship_name=edge["relationship_name"]) - - + graph_client = await get_graph_engine() + await graph_client.add_nodes([(node["id"], node) for node in topology["nodes"]]) + await graph_client.add_edges(( + edge["source_node_id"], + edge["target_node_id"], + edge["relationship_name"], + dict(relationship_name = edge["relationship_name"]), + ) for edge in topology["edges"]) else: - dataset_level_information = dataset_files[0][1] + dataset_level_information = files[0][1] # Extract the list of valid IDs from the explanations - valid_ids = {item['id'] for item in dataset_level_information} + valid_ids = {item["id"] for item in dataset_level_information} try: data = await self.load_data(file_path) flt_topology = await self.recursive_flatten(data) df = pd.DataFrame(flt_topology) - graph_client = await get_graph_client() - - print("df", df) + graph_client = await get_graph_engine() for _, row in df.iterrows(): node_data = row.to_dict() @@ -137,12 +133,9 @@ class TopologyEngine: if pd.notna(row.get("relationship_source")) and pd.notna(row.get("relationship_target")): await graph_client.add_edge(row["relationship_source"], row["relationship_target"], relationship_name=row["relationship_type"]) - for dataset in dataset_files: - print("dataset", dataset) - return except Exception as e: - raise RuntimeError(f"Failed to add graph topology from {file_path}: {e}") + raise RuntimeError(f"Failed to add graph topology from {file_path}: {e}") from e @@ -164,7 +157,7 @@ async def main(): from cognee.api.v1.add import add dataset_name = "explanations" print(os.getcwd()) - data_dir = os.path.abspath("../../../.data") + data_dir = os.path.abspath("../../.data") print(os.getcwd()) await add(f"data://{data_dir}", dataset_name="explanations") @@ -184,11 +177,11 @@ async def main(): print(dataset_files) topology_engine = TopologyEngine(infer=True) - file_path = 'example_data.json' # or 'example_data.csv' + file_path = "example_data.json" # or 'example_data.csv' # # # Adding graph topology graph = await topology_engine.add_graph_topology(file_path, dataset_files=dataset_files) - # print(graph) + print(graph) # Run the main function if __name__ == "__main__": diff --git a/cognee/shared/data_models.py b/cognee/shared/data_models.py index 582469d6c..98ea34290 100644 --- a/cognee/shared/data_models.py +++ b/cognee/shared/data_models.py @@ -148,31 +148,31 @@ class ContentType(BaseModel): type: str class TextContent(ContentType): - type: str = "TEXT" + type: str = "TEXTUAL_DOCUMENTS_USED_FOR_GENERAL_PURPOSES" subclass: List[TextSubclass] class AudioContent(ContentType): - type: str = "AUDIO" + type: str = "AUDIO_DOCUMENTS_USED_FOR_GENERAL_PURPOSES" subclass: List[AudioSubclass] class ImageContent(ContentType): - type: str = "IMAGE" + type: str = "IMAGE_DOCUMENTS_USED_FOR_GENERAL_PURPOSES" subclass: List[ImageSubclass] class VideoContent(ContentType): - type: str = "VIDEO" + type: str = "VIDEO_DOCUMENTS_USED_FOR_GENERAL_PURPOSES" subclass: List[VideoSubclass] class MultimediaContent(ContentType): - type: str = "MULTIMEDIA" + type: str = "MULTIMEDIA_DOCUMENTS_USED_FOR_GENERAL_PURPOSES" subclass: List[MultimediaSubclass] class Model3DContent(ContentType): - type: str = "3D_MODEL" + type: str = "3D_MODEL_DOCUMENTS_USED_FOR_GENERAL_PURPOSES" subclass: List[Model3DSubclass] class ProceduralContent(ContentType): - type: str = "PROCEDURAL" + type: str = "PROCEDURAL_DOCUMENTS_USED_FOR_GENERAL_PURPOSES" subclass: List[ProceduralSubclass] class DefaultContentPrediction(BaseModel): @@ -235,8 +235,8 @@ class Category(BaseModel): class Document(BaseModel): id: str + type: str title: str - description: Optional[str] = None class UserLocation(BaseModel): location_id: str @@ -255,10 +255,13 @@ class DefaultGraphModel(BaseModel): default_relationship: Relationship = Relationship(type = "has_properties") -class ResponseSummaryModel(BaseModel): - """ Response summary model and existing document id """ - document_id: str - response_summary: str +class ChunkSummary(BaseModel): + text: str + chunk_id: str + +class ChunkSummaries(BaseModel): + """ Relevant summary and chunk id """ + summaries: List[ChunkSummary] class MonitoringTool(str, Enum): diff --git a/cognee/shared/utils.py b/cognee/shared/utils.py index 4385577ea..4c1b53973 100644 --- a/cognee/shared/utils.py +++ b/cognee/shared/utils.py @@ -12,6 +12,7 @@ import tiktoken import nltk from posthog import Posthog from cognee.base_config import get_base_config +from cognee.infrastructure.databases.graph import get_graph_engine def send_telemetry(event_name: str): if os.getenv("TELEMETRY_DISABLED"): @@ -183,6 +184,18 @@ def prepare_nodes(graph, include_size=False): async def render_graph(graph, include_nodes=False, include_color=False, include_size=False, include_labels=False): await register_graphistry() + + if not isinstance(graph, nx.MultiDiGraph): + graph_engine = await get_graph_engine() + networkx_graph = nx.MultiDiGraph() + + (nodes, edges) = await graph_engine.get_graph_data() + + networkx_graph.add_nodes_from(nodes) + networkx_graph.add_edges_from(edges) + + graph = networkx_graph + edges = prepare_edges(graph) plotter = graphistry.edges(edges, "source", "target") diff --git a/cognee/tests/test_data/artificial-intelligence.pdf b/cognee/tests/test_data/artificial-intelligence.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7de338b8cfe5ec9120e1fb0b4a8d5dbc541b52ca GIT binary patch literal 29616 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 z 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 literal 0 HcmV?d00001 diff --git a/cognee/tests/test_library.py b/cognee/tests/test_library.py index 2c656247f..2cb32db14 100755 --- a/cognee/tests/test_library.py +++ b/cognee/tests/test_library.py @@ -1,91 +1,60 @@ -import logging import os +import logging +import pathlib +import cognee + +logging.basicConfig(level = logging.DEBUG) -logging.basicConfig(level=logging.DEBUG) async def main(): - from os import path - import pathlib - import cognee - logging.basicConfig(level=logging.DEBUG) + data_directory_path = str(pathlib.Path(os.path.join(pathlib.Path(__file__).parent, ".data_storage/test_library")).resolve()) + cognee.config.data_root_directory(data_directory_path) + cognee_directory_path = str(pathlib.Path(os.path.join(pathlib.Path(__file__).parent, ".cognee_system/test_library")).resolve()) + cognee.config.system_root_directory(cognee_directory_path) - # print("Working dir: ", str(pathlib.Path(__file__).parent)) - # data_directory_path = str(pathlib.Path(path.join(pathlib.Path(__file__).parent, "../../.data")).resolve()) - # print("Data dir: ", data_directory_path) - # cognee.config.data_root_directory(data_directory_path) - # - # cognee_directory_path = str(pathlib.Path(path.join(pathlib.Path(__file__).parent, "../../.cognee_system")).resolve()) - # print("System dir: ", cognee_directory_path) - # cognee.config.system_root_directory(cognee_directory_path) + await cognee.prune.prune_data() + await cognee.prune.prune_system(metadata = True) - logging.debug("CURRENCT CWD: %s", pathlib.Path(__file__).parent) - logging.debug("CURRENCT CWD: %s", os.getcwd()) + dataset_name = "artificial_intelligence" + ai_text_file_path = os.path.join(pathlib.Path(__file__).parent, "test_data/artificial-intelligence.pdf") + await cognee.add([ai_text_file_path], dataset_name) - dataset_name = "cs_explanations" + # text = """A quantum computer is a computer that takes advantage of quantum mechanical phenomena. + # At small scales, physical matter exhibits properties of both particles and waves, and quantum computing leverages this behavior, specifically quantum superposition and entanglement, using specialized hardware that supports the preparation and manipulation of quantum states. + # Classical physics cannot explain the operation of these quantum devices, and a scalable quantum computer could perform some calculations exponentially faster (with respect to input size scaling) than any modern "classical" computer. In particular, a large-scale quantum computer could break widely used encryption schemes and aid physicists in performing physical simulations; however, the current state of the technology is largely experimental and impractical, with several obstacles to useful applications. Moreover, scalable quantum computers do not hold promise for many practical tasks, and for many important tasks quantum speedups are proven impossible. + # The basic unit of information in quantum computing is the qubit, similar to the bit in traditional digital electronics. Unlike a classical bit, a qubit can exist in a superposition of its two "basis" states. When measuring a qubit, the result is a probabilistic output of a classical bit, therefore making quantum computers nondeterministic in general. If a quantum computer manipulates the qubit in a particular way, wave interference effects can amplify the desired measurement results. The design of quantum algorithms involves creating procedures that allow a quantum computer to perform calculations efficiently and quickly. + # Physically engineering high-quality qubits has proven challenging. If a physical qubit is not sufficiently isolated from its environment, it suffers from quantum decoherence, introducing noise into calculations. Paradoxically, perfectly isolating qubits is also undesirable because quantum computations typically need to initialize qubits, perform controlled qubit interactions, and measure the resulting quantum states. Each of those operations introduces errors and suffers from noise, and such inaccuracies accumulate. + # In principle, a non-quantum (classical) computer can solve the same computational problems as a quantum computer, given enough time. Quantum advantage comes in the form of time complexity rather than computability, and quantum complexity theory shows that some quantum algorithms for carefully selected tasks require exponentially fewer computational steps than the best known non-quantum algorithms. Such tasks can in theory be solved on a large-scale quantum computer whereas classical computers would not finish computations in any reasonable amount of time. However, quantum speedup is not universal or even typical across computational tasks, since basic tasks such as sorting are proven to not allow any asymptotic quantum speedup. Claims of quantum supremacy have drawn significant attention to the discipline, but are demonstrated on contrived tasks, while near-term practical use cases remain limited. + # """ - explanation_file_path = os.path.join(pathlib.Path(__file__).parent, "test_data/Natural_language_processing.txt") - await cognee.add([explanation_file_path], dataset_name) - - # dataset_name = "short_stories" - # # data_directory_path is defined above - # await cognee.add("data://" + "/Users/runner/work/cognee/cognee/./cognee/tests", dataset_name) - - text_1 = """A quantum computer is a computer that takes advantage of quantum mechanical phenomena. - At small scales, physical matter exhibits properties of both particles and waves, and quantum computing leverages this behavior, specifically quantum superposition and entanglement, using specialized hardware that supports the preparation and manipulation of quantum states. - Classical physics cannot explain the operation of these quantum devices, and a scalable quantum computer could perform some calculations exponentially faster (with respect to input size scaling) than any modern "classical" computer. In particular, a large-scale quantum computer could break widely used encryption schemes and aid physicists in performing physical simulations; however, the current state of the technology is largely experimental and impractical, with several obstacles to useful applications. Moreover, scalable quantum computers do not hold promise for many practical tasks, and for many important tasks quantum speedups are proven impossible. - The basic unit of information in quantum computing is the qubit, similar to the bit in traditional digital electronics. Unlike a classical bit, a qubit can exist in a superposition of its two "basis" states. When measuring a qubit, the result is a probabilistic output of a classical bit, therefore making quantum computers nondeterministic in general. If a quantum computer manipulates the qubit in a particular way, wave interference effects can amplify the desired measurement results. The design of quantum algorithms involves creating procedures that allow a quantum computer to perform calculations efficiently and quickly. - Physically engineering high-quality qubits has proven challenging. If a physical qubit is not sufficiently isolated from its environment, it suffers from quantum decoherence, introducing noise into calculations. Paradoxically, perfectly isolating qubits is also undesirable because quantum computations typically need to initialize qubits, perform controlled qubit interactions, and measure the resulting quantum states. Each of those operations introduces errors and suffers from noise, and such inaccuracies accumulate. - In principle, a non-quantum (classical) computer can solve the same computational problems as a quantum computer, given enough time. Quantum advantage comes in the form of time complexity rather than computability, and quantum complexity theory shows that some quantum algorithms for carefully selected tasks require exponentially fewer computational steps than the best known non-quantum algorithms. Such tasks can in theory be solved on a large-scale quantum computer whereas classical computers would not finish computations in any reasonable amount of time. However, quantum speedup is not universal or even typical across computational tasks, since basic tasks such as sorting are proven to not allow any asymptotic quantum speedup. Claims of quantum supremacy have drawn significant attention to the discipline, but are demonstrated on contrived tasks, while near-term practical use cases remain limited. - """ - - text_2 = """A large language model (LLM) is a language model notable for its ability to achieve general-purpose language generation and other natural language processing tasks such as classification. LLMs acquire these abilities by learning statistical relationships from text documents during a computationally intensive self-supervised and semi-supervised training process. LLMs can be used for text generation, a form of generative AI, by taking an input text and repeatedly predicting the next token or word. + text = """A large language model (LLM) is a language model notable for its ability to achieve general-purpose language generation and other natural language processing tasks such as classification. LLMs acquire these abilities by learning statistical relationships from text documents during a computationally intensive self-supervised and semi-supervised training process. LLMs can be used for text generation, a form of generative AI, by taking an input text and repeatedly predicting the next token or word. LLMs are artificial neural networks. The largest and most capable, as of March 2024, are built with a decoder-only transformer-based architecture while some recent implementations are based on other architectures, such as recurrent neural network variants and Mamba (a state space model). Up to 2020, fine tuning was the only way a model could be adapted to be able to accomplish specific tasks. Larger sized models, such as GPT-3, however, can be prompt-engineered to achieve similar results.[6] They are thought to acquire knowledge about syntax, semantics and "ontology" inherent in human language corpora, but also inaccuracies and biases present in the corpora. Some notable LLMs are OpenAI's GPT series of models (e.g., GPT-3.5 and GPT-4, used in ChatGPT and Microsoft Copilot), Google's PaLM and Gemini (the latter of which is currently used in the chatbot of the same name), xAI's Grok, Meta's LLaMA family of open-source models, Anthropic's Claude models, Mistral AI's open source models, and Databricks' open source DBRX. """ + await cognee.add([text], dataset_name) - await cognee.cognify([ "cs_explanations"]) + await cognee.cognify([dataset_name], root_node_id = "ROOT") - search_results = await cognee.search("SIMILARITY", { "query": "computer science" }) + search_results = await cognee.search("TRAVERSE", { "query": "Text" }) assert len(search_results) != 0, "The search results list is empty." - print("The search results list is not empty.") - - search_results = await cognee.search("CATEGORIES", { "query": "DefaultGraphModel__default_user" }) - assert len(search_results) != 0, "The search results list is empty." - print("The search results list is not empty.") - - - search_results = await cognee.search("NEIGHBOR", { "query": "DefaultGraphModel__default_user" }) - assert len(search_results) != 0, "The search results list is empty." - print("The search results list is not empty.") - + print("\n\nExtracted sentences are:\n") + for result in search_results: + print(f"{result}\n") search_results = await cognee.search("SUMMARY", { "query": "Work and computers" }) - assert len(search_results) != 0, "The search results list is empty." - print("The search results list is not empty.") + assert len(search_results) != 0, "Query related summaries don't exist." + print("\n\nQuery related summaries exist:\n") + for result in search_results: + print(f"{result}\n") - search_results = await cognee.search("ADJACENT", { "query": "DefaultGraphModel__default_user" }) - assert len(search_results) != 0, "The search results list is empty." - print("The search results list is not empty.") - - # - # dataset_name = "cs_explanations" - # await cognee.add( - # [ - # text_1, - # text_2 - # ], - # dataset_name - # ) - - # search_results = cognee.search("SIMILARITY", "computer science") - # if len(search_results) == 0: - # print("The similarity search results list is empty.") - # raise Exception("The search results list is empty.") - # else: - # print("The search results list is not empty.") + search_results = await cognee.search("ADJACENT", { "query": "Articles" }) + assert len(search_results) != 0, "ROOT node has no neighbours." + print("\n\nROOT node has neighbours.\n") + for result in search_results: + print(f"{result}\n") if __name__ == "__main__": diff --git a/cognee/tests/test_neo4j.py b/cognee/tests/test_neo4j.py index b25519059..c4a871abe 100644 --- a/cognee/tests/test_neo4j.py +++ b/cognee/tests/test_neo4j.py @@ -1,41 +1,27 @@ -import logging import os +import logging +import pathlib +import cognee logging.basicConfig(level=logging.DEBUG) async def main(): - from os import path - import pathlib - import cognee - logging.basicConfig(level=logging.DEBUG) - - # print("Working dir: ", str(pathlib.Path(__file__).parent)) - # data_directory_path = str(pathlib.Path(path.join(pathlib.Path(__file__).parent, "../../.data")).resolve()) - # print("Data dir: ", data_directory_path) - # cognee.config.data_root_directory(data_directory_path) - # - # cognee_directory_path = str(pathlib.Path(path.join(pathlib.Path(__file__).parent, "../../.cognee_system")).resolve()) - # print("System dir: ", cognee_directory_path) - # cognee.config.system_root_directory(cognee_directory_path) - cognee.config.set_graph_database_provider("neo4j") + data_directory_path = str(pathlib.Path(os.path.join(pathlib.Path(__file__).parent, ".data_storage/test_neo4j")).resolve()) + cognee.config.data_root_directory(data_directory_path) + cognee_directory_path = str(pathlib.Path(os.path.join(pathlib.Path(__file__).parent, ".cognee_system/test_neo4j")).resolve()) + cognee.config.system_root_directory(cognee_directory_path) - await cognee.prune.prune_system() - - logging.debug("CURRENCT CWD: %s", pathlib.Path(__file__).parent) - logging.debug("CURRENCT CWD: %s", os.getcwd()) + await cognee.prune.prune_data() + await cognee.prune.prune_system(metadata = True) dataset_name = "cs_explanations" explanation_file_path = os.path.join(pathlib.Path(__file__).parent, "test_data/Natural_language_processing.txt") await cognee.add([explanation_file_path], dataset_name) - # dataset_name = "short_stories" - # # data_directory_path is defined above - # await cognee.add("data://" + "/Users/runner/work/cognee/cognee/./cognee/tests", dataset_name) - - text_1 = """A quantum computer is a computer that takes advantage of quantum mechanical phenomena. + text = """A quantum computer is a computer that takes advantage of quantum mechanical phenomena. At small scales, physical matter exhibits properties of both particles and waves, and quantum computing leverages this behavior, specifically quantum superposition and entanglement, using specialized hardware that supports the preparation and manipulation of quantum states. Classical physics cannot explain the operation of these quantum devices, and a scalable quantum computer could perform some calculations exponentially faster (with respect to input size scaling) than any modern "classical" computer. In particular, a large-scale quantum computer could break widely used encryption schemes and aid physicists in performing physical simulations; however, the current state of the technology is largely experimental and impractical, with several obstacles to useful applications. Moreover, scalable quantum computers do not hold promise for many practical tasks, and for many important tasks quantum speedups are proven impossible. The basic unit of information in quantum computing is the qubit, similar to the bit in traditional digital electronics. Unlike a classical bit, a qubit can exist in a superposition of its two "basis" states. When measuring a qubit, the result is a probabilistic output of a classical bit, therefore making quantum computers nondeterministic in general. If a quantum computer manipulates the qubit in a particular way, wave interference effects can amplify the desired measurement results. The design of quantum algorithms involves creating procedures that allow a quantum computer to perform calculations efficiently and quickly. @@ -43,36 +29,29 @@ async def main(): In principle, a non-quantum (classical) computer can solve the same computational problems as a quantum computer, given enough time. Quantum advantage comes in the form of time complexity rather than computability, and quantum complexity theory shows that some quantum algorithms for carefully selected tasks require exponentially fewer computational steps than the best known non-quantum algorithms. Such tasks can in theory be solved on a large-scale quantum computer whereas classical computers would not finish computations in any reasonable amount of time. However, quantum speedup is not universal or even typical across computational tasks, since basic tasks such as sorting are proven to not allow any asymptotic quantum speedup. Claims of quantum supremacy have drawn significant attention to the discipline, but are demonstrated on contrived tasks, while near-term practical use cases remain limited. """ - text_2 = """A large language model (LLM) is a language model notable for its ability to achieve general-purpose language generation and other natural language processing tasks such as classification. LLMs acquire these abilities by learning statistical relationships from text documents during a computationally intensive self-supervised and semi-supervised training process. LLMs can be used for text generation, a form of generative AI, by taking an input text and repeatedly predicting the next token or word. - LLMs are artificial neural networks. The largest and most capable, as of March 2024, are built with a decoder-only transformer-based architecture while some recent implementations are based on other architectures, such as recurrent neural network variants and Mamba (a state space model). - Up to 2020, fine tuning was the only way a model could be adapted to be able to accomplish specific tasks. Larger sized models, such as GPT-3, however, can be prompt-engineered to achieve similar results.[6] They are thought to acquire knowledge about syntax, semantics and "ontology" inherent in human language corpora, but also inaccuracies and biases present in the corpora. - Some notable LLMs are OpenAI's GPT series of models (e.g., GPT-3.5 and GPT-4, used in ChatGPT and Microsoft Copilot), Google's PaLM and Gemini (the latter of which is currently used in the chatbot of the same name), xAI's Grok, Meta's LLaMA family of open-source models, Anthropic's Claude models, Mistral AI's open source models, and Databricks' open source DBRX. - """ + await cognee.add([text], dataset_name) - await cognee.cognify(["cs_explanations"]) + await cognee.cognify([dataset_name]) - search_results = await cognee.search("SIMILARITY", {"query": "computer science"}) + search_results = await cognee.search("TRAVERSE", { "query": "Artificial intelligence" }) assert len(search_results) != 0, "The search results list is empty." - print("The search results list is not empty.") - # - # search_results = await cognee.search("CATEGORIES", {"query": "DefaultGraphModel__default_user"}) - # assert len(search_results) != 0, "The search results list is empty." - # print("The search results list is not empty.") - # - # search_results = await cognee.search("NEIGHBOR", {"query": "DefaultGraphModel__default_user"}) - # assert len(search_results) != 0, "The search results list is empty." - # print("The search results list is not empty.") - # - # search_results = await cognee.search("SUMMARY", {"query": "Work and computers"}) - # assert len(search_results) != 0, "The search results list is empty." - # print("The search results list is not empty.") - # - # search_results = await cognee.search("ADJACENT", {"query": "DefaultGraphModel__default_user"}) - # assert len(search_results) != 0, "The search results list is empty." - # print("The search results list is not empty.") + print("\n\nExtracted sentences are:\n") + for result in search_results: + print(f"{result}\n") + search_results = await cognee.search("SUMMARY", { "query": "Work and computers" }) + assert len(search_results) != 0, "Query related summaries don't exist." + print("\n\nQuery related summaries exist:\n") + for result in search_results: + print(f"{result}\n") + + search_results = await cognee.search("ADJACENT", { "query": "ROOT" }) + assert len(search_results) != 0, "ROOT node has no neighbours." + print("\n\nROOT node has neighbours.\n") + for result in search_results: + print(f"{result}\n") if __name__ == "__main__": import asyncio - asyncio.run(main()) \ No newline at end of file + asyncio.run(main()) diff --git a/cognee/tests/test_qdrant.py b/cognee/tests/test_qdrant.py index 4085fe5f4..9ee7a0d7d 100644 --- a/cognee/tests/test_qdrant.py +++ b/cognee/tests/test_qdrant.py @@ -1,39 +1,28 @@ -import logging + import os +import logging +import pathlib +import cognee logging.basicConfig(level=logging.DEBUG) async def main(): - from os import path - import pathlib - import cognee - logging.basicConfig(level=logging.DEBUG) - - # print("Working dir: ", str(pathlib.Path(__file__).parent)) - # data_directory_path = str(pathlib.Path(path.join(pathlib.Path(__file__).parent, "../../.data")).resolve()) - # print("Data dir: ", data_directory_path) - # cognee.config.data_root_directory(data_directory_path) - # - # cognee_directory_path = str(pathlib.Path(path.join(pathlib.Path(__file__).parent, "../../.cognee_system")).resolve()) - # print("System dir: ", cognee_directory_path) - # cognee.config.system_root_directory(cognee_directory_path) - cognee.config.set_vector_engine_provider("qdrant") + data_directory_path = str(pathlib.Path(os.path.join(pathlib.Path(__file__).parent, ".data_storage/test_qdrant")).resolve()) + cognee.config.data_root_directory(data_directory_path) + cognee_directory_path = str(pathlib.Path(os.path.join(pathlib.Path(__file__).parent, ".cognee_system/test_qdrant")).resolve()) + cognee.config.system_root_directory(cognee_directory_path) - logging.debug("CURRENCT CWD: %s", pathlib.Path(__file__).parent) - logging.debug("CURRENCT CWD: %s", os.getcwd()) + await cognee.prune.prune_data() + await cognee.prune.prune_system(metadata = True) dataset_name = "cs_explanations" explanation_file_path = os.path.join(pathlib.Path(__file__).parent, "test_data/Natural_language_processing.txt") await cognee.add([explanation_file_path], dataset_name) - # dataset_name = "short_stories" - # # data_directory_path is defined above - # await cognee.add("data://" + "/Users/runner/work/cognee/cognee/./cognee/tests", dataset_name) - - text_1 = """A quantum computer is a computer that takes advantage of quantum mechanical phenomena. + text = """A quantum computer is a computer that takes advantage of quantum mechanical phenomena. At small scales, physical matter exhibits properties of both particles and waves, and quantum computing leverages this behavior, specifically quantum superposition and entanglement, using specialized hardware that supports the preparation and manipulation of quantum states. Classical physics cannot explain the operation of these quantum devices, and a scalable quantum computer could perform some calculations exponentially faster (with respect to input size scaling) than any modern "classical" computer. In particular, a large-scale quantum computer could break widely used encryption schemes and aid physicists in performing physical simulations; however, the current state of the technology is largely experimental and impractical, with several obstacles to useful applications. Moreover, scalable quantum computers do not hold promise for many practical tasks, and for many important tasks quantum speedups are proven impossible. The basic unit of information in quantum computing is the qubit, similar to the bit in traditional digital electronics. Unlike a classical bit, a qubit can exist in a superposition of its two "basis" states. When measuring a qubit, the result is a probabilistic output of a classical bit, therefore making quantum computers nondeterministic in general. If a quantum computer manipulates the qubit in a particular way, wave interference effects can amplify the desired measurement results. The design of quantum algorithms involves creating procedures that allow a quantum computer to perform calculations efficiently and quickly. @@ -41,34 +30,27 @@ async def main(): In principle, a non-quantum (classical) computer can solve the same computational problems as a quantum computer, given enough time. Quantum advantage comes in the form of time complexity rather than computability, and quantum complexity theory shows that some quantum algorithms for carefully selected tasks require exponentially fewer computational steps than the best known non-quantum algorithms. Such tasks can in theory be solved on a large-scale quantum computer whereas classical computers would not finish computations in any reasonable amount of time. However, quantum speedup is not universal or even typical across computational tasks, since basic tasks such as sorting are proven to not allow any asymptotic quantum speedup. Claims of quantum supremacy have drawn significant attention to the discipline, but are demonstrated on contrived tasks, while near-term practical use cases remain limited. """ - text_2 = """A large language model (LLM) is a language model notable for its ability to achieve general-purpose language generation and other natural language processing tasks such as classification. LLMs acquire these abilities by learning statistical relationships from text documents during a computationally intensive self-supervised and semi-supervised training process. LLMs can be used for text generation, a form of generative AI, by taking an input text and repeatedly predicting the next token or word. - LLMs are artificial neural networks. The largest and most capable, as of March 2024, are built with a decoder-only transformer-based architecture while some recent implementations are based on other architectures, such as recurrent neural network variants and Mamba (a state space model). - Up to 2020, fine tuning was the only way a model could be adapted to be able to accomplish specific tasks. Larger sized models, such as GPT-3, however, can be prompt-engineered to achieve similar results.[6] They are thought to acquire knowledge about syntax, semantics and "ontology" inherent in human language corpora, but also inaccuracies and biases present in the corpora. - Some notable LLMs are OpenAI's GPT series of models (e.g., GPT-3.5 and GPT-4, used in ChatGPT and Microsoft Copilot), Google's PaLM and Gemini (the latter of which is currently used in the chatbot of the same name), xAI's Grok, Meta's LLaMA family of open-source models, Anthropic's Claude models, Mistral AI's open source models, and Databricks' open source DBRX. - """ + await cognee.add([text], dataset_name) - await cognee.cognify(["cs_explanations"]) + await cognee.cognify([dataset_name]) - search_results = await cognee.search("SIMILARITY", {"query": "computer science"}) + search_results = await cognee.search("TRAVERSE", { "query": "Artificial intelligence" }) assert len(search_results) != 0, "The search results list is empty." - print("The search results list is not empty.") + print("\n\nExtracted sentences are:\n") + for result in search_results: + print(f"{result}\n") - search_results = await cognee.search("CATEGORIES", {"query": "DefaultGraphModel__default_user"}) - assert len(search_results) != 0, "The search results list is empty." - print("The search results list is not empty.") - - search_results = await cognee.search("NEIGHBOR", {"query": "DefaultGraphModel__default_user"}) - assert len(search_results) != 0, "The search results list is empty." - print("The search results list is not empty.") - - search_results = await cognee.search("SUMMARY", {"query": "Work and computers"}) - assert len(search_results) != 0, "The search results list is empty." - print("The search results list is not empty.") - - search_results = await cognee.search("ADJACENT", {"query": "DefaultGraphModel__default_user"}) - assert len(search_results) != 0, "The search results list is empty." - print("The search results list is not empty.") + search_results = await cognee.search("SUMMARY", { "query": "Work and computers" }) + assert len(search_results) != 0, "Query related summaries don't exist." + print("\n\nQuery related summaries exist:\n") + for result in search_results: + print(f"{result}\n") + search_results = await cognee.search("ADJACENT", { "query": "ROOT" }) + assert len(search_results) != 0, "ROOT node has no neighbours." + print("\n\nROOT node has neighbours.\n") + for result in search_results: + print(f"{result}\n") if __name__ == "__main__": diff --git a/cognee/tests/test_weaviate.py b/cognee/tests/test_weaviate.py index 478cfb3ea..09d8ee62b 100644 --- a/cognee/tests/test_weaviate.py +++ b/cognee/tests/test_weaviate.py @@ -1,27 +1,56 @@ -import asyncio +import os +import logging +import pathlib +import cognee -async def test_weaviate_integration(): - from cognee import config, prune, add, cognify, search +logging.basicConfig(level=logging.DEBUG) - config.set_vector_engine_provider("weaviate") - # config.set_vector_db_url("TEST_URL") - # config.set_vector_db_key("TEST_KEY") +async def main(): + cognee.config.set_vector_engine_provider("weaviate") + data_directory_path = str(pathlib.Path(os.path.join(pathlib.Path(__file__).parent, ".data_storage/test_weaviate")).resolve()) + cognee.config.data_root_directory(data_directory_path) + cognee_directory_path = str(pathlib.Path(os.path.join(pathlib.Path(__file__).parent, ".cognee_system/test_weaviate")).resolve()) + cognee.config.system_root_directory(cognee_directory_path) - prune.prune_system() + await cognee.prune.prune_data() + await cognee.prune.prune_system(metadata = True) - text = """ - Incapillo is a Pleistocene-age caldera (a depression formed by the collapse of a volcano) in the La Rioja Province of Argentina. It is the southernmost volcanic centre in the Andean Central Volcanic Zone (CVZ) that erupted during the Pleistocene. Incapillo is one of several ignimbrite[a] or caldera systems that, along with 44 active stratovolcanoes, are part of the CVZ. - Subduction of the Nazca Plate beneath the South American Plate is responsible for most of the volcanism in the CVZ. After activity in the volcanic arc of the western Maricunga Belt ceased six million years ago, volcanism commenced in the Incapillo region, forming the high volcanic edifices Monte Pissis, Cerro Bonete Chico and Sierra de Veladero. Later, a number of lava domes were emplaced between these volcanoes. - Incapillo is the source of the Incapillo ignimbrite, a medium-sized deposit comparable to the Katmai ignimbrite. The Incapillo ignimbrite was erupted 0.52 ± 0.03 and 0.51 ± 0.04 million years ago and has a volume of about 20.4 cubic kilometres (4.9 cu mi). A caldera with dimensions of 5 by 6 kilometres (3.1 mi × 3.7 mi) formed during the eruption. Later volcanism generated more lava domes within the caldera and a debris flow in the Sierra de Veladero. The lake within the caldera may overlie an area of ongoing hydrothermal activity. + dataset_name = "cs_explanations" + + explanation_file_path = os.path.join(pathlib.Path(__file__).parent, "test_data/Natural_language_processing.txt") + await cognee.add([explanation_file_path], dataset_name) + + text = """A quantum computer is a computer that takes advantage of quantum mechanical phenomena. + At small scales, physical matter exhibits properties of both particles and waves, and quantum computing leverages this behavior, specifically quantum superposition and entanglement, using specialized hardware that supports the preparation and manipulation of quantum states. + Classical physics cannot explain the operation of these quantum devices, and a scalable quantum computer could perform some calculations exponentially faster (with respect to input size scaling) than any modern "classical" computer. In particular, a large-scale quantum computer could break widely used encryption schemes and aid physicists in performing physical simulations; however, the current state of the technology is largely experimental and impractical, with several obstacles to useful applications. Moreover, scalable quantum computers do not hold promise for many practical tasks, and for many important tasks quantum speedups are proven impossible. + The basic unit of information in quantum computing is the qubit, similar to the bit in traditional digital electronics. Unlike a classical bit, a qubit can exist in a superposition of its two "basis" states. When measuring a qubit, the result is a probabilistic output of a classical bit, therefore making quantum computers nondeterministic in general. If a quantum computer manipulates the qubit in a particular way, wave interference effects can amplify the desired measurement results. The design of quantum algorithms involves creating procedures that allow a quantum computer to perform calculations efficiently and quickly. + Physically engineering high-quality qubits has proven challenging. If a physical qubit is not sufficiently isolated from its environment, it suffers from quantum decoherence, introducing noise into calculations. Paradoxically, perfectly isolating qubits is also undesirable because quantum computations typically need to initialize qubits, perform controlled qubit interactions, and measure the resulting quantum states. Each of those operations introduces errors and suffers from noise, and such inaccuracies accumulate. + In principle, a non-quantum (classical) computer can solve the same computational problems as a quantum computer, given enough time. Quantum advantage comes in the form of time complexity rather than computability, and quantum complexity theory shows that some quantum algorithms for carefully selected tasks require exponentially fewer computational steps than the best known non-quantum algorithms. Such tasks can in theory be solved on a large-scale quantum computer whereas classical computers would not finish computations in any reasonable amount of time. However, quantum speedup is not universal or even typical across computational tasks, since basic tasks such as sorting are proven to not allow any asymptotic quantum speedup. Claims of quantum supremacy have drawn significant attention to the discipline, but are demonstrated on contrived tasks, while near-term practical use cases remain limited. """ - await add(text) + await cognee.add([text], dataset_name) - await cognify() + await cognee.cognify([dataset_name]) - result = await search("SIMILARITY", { "query": "volcanic eruption" }) + search_results = await cognee.search("TRAVERSE", { "query": "Artificial intelligence" }) + assert len(search_results) != 0, "The search results list is empty." + print("\n\nExtracted sentences are:\n") + for result in search_results: + print(f"{result}\n") + + search_results = await cognee.search("SUMMARY", { "query": "Work and computers" }) + assert len(search_results) != 0, "Query related summaries don't exist." + print("\n\nQuery related summaries exist:\n") + for result in search_results: + print(f"{result}\n") + + search_results = await cognee.search("ADJACENT", { "query": "ROOT" }) + assert len(search_results) != 0, "ROOT node has no neighbours." + print("\n\nROOT node has neighbours.\n") + for result in search_results: + print(f"{result}\n") - print(result) if __name__ == "__main__": - asyncio.run(test_weaviate_integration()) + import asyncio + asyncio.run(main()) diff --git a/docker-compose-vanilla.yml b/docker-compose-vanilla.yml deleted file mode 100644 index 07bae272d..000000000 --- a/docker-compose-vanilla.yml +++ /dev/null @@ -1,41 +0,0 @@ -services: - cognee: - container_name: cognee - networks: - - cognee-network - build: - context: . - dockerfile: Dockerfile - volumes: - - .:/app - - /app/cognee-frontend/ # Ignore frontend code - environment: - - HOST=0.0.0.0 - - ENVIRONMENT=local - - PYTHONPATH=. - ports: - - 8000:8000 - # - 5678:5678 # Debugging - deploy: - resources: - limits: - cpus: 4.0 - memory: 8GB - - frontend: - container_name: frontend - build: - context: ./cognee-frontend - dockerfile: Dockerfile - volumes: - - ./cognee-frontend/src:/app/src - - ./cognee-frontend/public:/app/public - ports: - - 3000:3000 - # - 9229:9229 # Debugging - networks: - - cognee-network - -networks: - cognee-network: - name: cognee-network diff --git a/docker-compose.yml b/docker-compose.yml index a23630091..21f6903b7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,7 +19,7 @@ services: deploy: resources: limits: - cpus: 4.0 + cpus: '4.0' memory: 8GB frontend: diff --git a/notebooks/full_run.ipynb b/notebooks/full_run.ipynb index 08d217ea5..3d094e323 100644 --- a/notebooks/full_run.ipynb +++ b/notebooks/full_run.ipynb @@ -113,7 +113,7 @@ "source": [ "import graphistry\n", "from cognee.shared.utils import render_graph\n", - "from cognee.infrastructure.databases.graph.get_graph_client import get_graph_client, GraphDBType\n", + "from cognee.infrastructure.databases.graph.get_graph_engine import get_graph_engine, GraphDBType\n", "from cognee.base_config import get_base_config\n", "\n", "config = get_base_config()\n", @@ -124,7 +124,7 @@ " password = config.graphistry_password\n", ")\n", "\n", - "graph_client = await get_graph_client(GraphDBType.NETWORKX, \"cognee_graph.pkl\")\n", + "graph_client = await get_graph_engine()\n", "graph = graph_client.graph\n", "\n", "await render_graph(graph)\n" @@ -139,7 +139,7 @@ "source": [ "from os import path\n", "import cognee\n", - "from cognee.infrastructure.databases.graph.get_graph_client import get_graph_client, GraphDBType\n", + "from cognee.infrastructure.databases.graph.get_graph_engine import get_graph_engine, GraphDBType\n", "from cognee.modules.search.vector.search_similarity import search_similarity\n", "\n", "data_directory_path = path.abspath(\"../.data\")\n", @@ -148,7 +148,7 @@ "cognee_directory_path = path.abspath(\"../.cognee_system\")\n", "cognee.config.system_root_directory(cognee_directory_path)\n", "\n", - "graph_client = await get_graph_client(GraphDBType.NETWORKX)\n", + "graph_client = await get_graph_engine()\n", "graph = graph_client.graph\n", "\n", "results = await search_similarity(\"Who are French girls?\", graph)\n", diff --git a/poetry.lock b/poetry.lock index ab395dfba..47892189c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "aiofiles" @@ -286,13 +286,13 @@ test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock [[package]] name = "astroid" -version = "3.2.2" +version = "3.2.3" description = "An abstract syntax tree for Python with inference support." optional = false python-versions = ">=3.8.0" files = [ - {file = "astroid-3.2.2-py3-none-any.whl", hash = "sha256:e8a0083b4bb28fcffb6207a3bfc9e5d0a68be951dd7e336d5dcf639c682388c0"}, - {file = "astroid-3.2.2.tar.gz", hash = "sha256:8ead48e31b92b2e217b6c9733a21afafe479d52d6e164dd25fb1a770c7c3cf94"}, + {file = "astroid-3.2.3-py3-none-any.whl", hash = "sha256:3eae9ea67c11c858cdd2c91337d2e816bd019ac897ca07d7b346ac10105fceb3"}, + {file = "astroid-3.2.3.tar.gz", hash = "sha256:7099b5a60985529d8d46858befa103b82d0d05a5a5e8b816b5303ed96075e1d9"}, ] [package.dependencies] @@ -414,6 +414,17 @@ files = [ {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, ] +[[package]] +name = "backports-strenum" +version = "1.3.1" +description = "Base class for creating enumerated constants that are also subclasses of str" +optional = false +python-versions = ">=3.8.6,<3.11" +files = [ + {file = "backports_strenum-1.3.1-py3-none-any.whl", hash = "sha256:cdcfe36dc897e2615dc793b7d3097f54d359918fc448754a517e6f23044ccf83"}, + {file = "backports_strenum-1.3.1.tar.gz", hash = "sha256:77c52407342898497714f0596e86188bb7084f89063226f4ba66863482f42414"}, +] + [[package]] name = "beautifulsoup4" version = "4.12.3" @@ -547,17 +558,17 @@ numpy = {version = ">=1.19.0", markers = "python_version >= \"3.9\""} [[package]] name = "boto3" -version = "1.34.122" +version = "1.34.145" description = "The AWS SDK for Python" optional = false python-versions = ">=3.8" files = [ - {file = "boto3-1.34.122-py3-none-any.whl", hash = "sha256:b2d7400ff84fa547e53b3d9acfa3c95d65d45b5886ba1ede1f7df4768d1cc0b1"}, - {file = "boto3-1.34.122.tar.gz", hash = "sha256:56840d8ce91654d182f1c113f0791fa2113c3aa43230c50b4481f235348a6037"}, + {file = "boto3-1.34.145-py3-none-any.whl", hash = "sha256:69d5afb7a017d07dd6bdfb680d2912d5d369b3fafa0a45161207d9f393b14d7e"}, + {file = "boto3-1.34.145.tar.gz", hash = "sha256:ac770fb53dde1743aec56bd8e56b7ee2e2f5ad42a37825968ec4ff8428822640"}, ] [package.dependencies] -botocore = ">=1.34.122,<1.35.0" +botocore = ">=1.34.145,<1.35.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -566,13 +577,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.34.122" +version = "1.34.145" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" files = [ - {file = "botocore-1.34.122-py3-none-any.whl", hash = "sha256:6d75df3af831b62f0c7baa109728d987e0a8d34bfadf0476eb32e2f29a079a36"}, - {file = "botocore-1.34.122.tar.gz", hash = "sha256:9374e16a36f1062c3e27816e8599b53eba99315dfac71cc84fc3aee3f5d3cbe3"}, + {file = "botocore-1.34.145-py3-none-any.whl", hash = "sha256:2e72e262de02adcb0264ac2bac159a28f55dbba8d9e52aa0308773a42950dff5"}, + {file = "botocore-1.34.145.tar.gz", hash = "sha256:edf0fb4c02186ae29b76263ac5fda18b0a085d334a310551c9984407cf1079e6"}, ] [package.dependencies] @@ -588,24 +599,24 @@ crt = ["awscrt (==0.20.11)"] [[package]] name = "cachetools" -version = "5.3.3" +version = "5.4.0" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.7" files = [ - {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, - {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, + {file = "cachetools-5.4.0-py3-none-any.whl", hash = "sha256:3ae3b49a3d5e28a77a0be2b37dbcb89005058959cb2323858c2657c4a8cab474"}, + {file = "cachetools-5.4.0.tar.gz", hash = "sha256:b8adc2e7c07f105ced7bc56dbb6dfbe7c4a00acce20e2227b3f355be89bc6827"}, ] [[package]] name = "cairocffi" -version = "1.7.0" +version = "1.7.1" description = "cffi-based cairo bindings for Python" optional = false python-versions = ">=3.8" files = [ - {file = "cairocffi-1.7.0-py3-none-any.whl", hash = "sha256:1f29a8d41dbda4090c0aa33bcdea64f3b493e95f74a43ea107c4a8a7b7f632ef"}, - {file = "cairocffi-1.7.0.tar.gz", hash = "sha256:7761863603894305f3160eca68452f373433ca8745ab7dd445bd2c6ce50dcab7"}, + {file = "cairocffi-1.7.1-py3-none-any.whl", hash = "sha256:9803a0e11f6c962f3b0ae2ec8ba6ae45e957a146a004697a1ac1bbf16b073b3f"}, + {file = "cairocffi-1.7.1.tar.gz", hash = "sha256:2e48ee864884ec4a3a34bfa8c9ab9999f688286eb714a15a43ec9d068c36557b"}, ] [package.dependencies] @@ -651,13 +662,13 @@ files = [ [[package]] name = "certifi" -version = "2024.6.2" +version = "2024.7.4" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"}, - {file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"}, + {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, + {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, ] [[package]] @@ -982,63 +993,63 @@ test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] [[package]] name = "coverage" -version = "7.5.3" +version = "7.6.0" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.5.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a6519d917abb15e12380406d721e37613e2a67d166f9fb7e5a8ce0375744cd45"}, - {file = "coverage-7.5.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:aea7da970f1feccf48be7335f8b2ca64baf9b589d79e05b9397a06696ce1a1ec"}, - {file = "coverage-7.5.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:923b7b1c717bd0f0f92d862d1ff51d9b2b55dbbd133e05680204465f454bb286"}, - {file = "coverage-7.5.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62bda40da1e68898186f274f832ef3e759ce929da9a9fd9fcf265956de269dbc"}, - {file = "coverage-7.5.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8b7339180d00de83e930358223c617cc343dd08e1aa5ec7b06c3a121aec4e1d"}, - {file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:25a5caf742c6195e08002d3b6c2dd6947e50efc5fc2c2205f61ecb47592d2d83"}, - {file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:05ac5f60faa0c704c0f7e6a5cbfd6f02101ed05e0aee4d2822637a9e672c998d"}, - {file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:239a4e75e09c2b12ea478d28815acf83334d32e722e7433471fbf641c606344c"}, - {file = "coverage-7.5.3-cp310-cp310-win32.whl", hash = "sha256:a5812840d1d00eafae6585aba38021f90a705a25b8216ec7f66aebe5b619fb84"}, - {file = "coverage-7.5.3-cp310-cp310-win_amd64.whl", hash = "sha256:33ca90a0eb29225f195e30684ba4a6db05dbef03c2ccd50b9077714c48153cac"}, - {file = "coverage-7.5.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f81bc26d609bf0fbc622c7122ba6307993c83c795d2d6f6f6fd8c000a770d974"}, - {file = "coverage-7.5.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7cec2af81f9e7569280822be68bd57e51b86d42e59ea30d10ebdbb22d2cb7232"}, - {file = "coverage-7.5.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55f689f846661e3f26efa535071775d0483388a1ccfab899df72924805e9e7cd"}, - {file = "coverage-7.5.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50084d3516aa263791198913a17354bd1dc627d3c1639209640b9cac3fef5807"}, - {file = "coverage-7.5.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:341dd8f61c26337c37988345ca5c8ccabeff33093a26953a1ac72e7d0103c4fb"}, - {file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ab0b028165eea880af12f66086694768f2c3139b2c31ad5e032c8edbafca6ffc"}, - {file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5bc5a8c87714b0c67cfeb4c7caa82b2d71e8864d1a46aa990b5588fa953673b8"}, - {file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:38a3b98dae8a7c9057bd91fbf3415c05e700a5114c5f1b5b0ea5f8f429ba6614"}, - {file = "coverage-7.5.3-cp311-cp311-win32.whl", hash = "sha256:fcf7d1d6f5da887ca04302db8e0e0cf56ce9a5e05f202720e49b3e8157ddb9a9"}, - {file = "coverage-7.5.3-cp311-cp311-win_amd64.whl", hash = "sha256:8c836309931839cca658a78a888dab9676b5c988d0dd34ca247f5f3e679f4e7a"}, - {file = "coverage-7.5.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:296a7d9bbc598e8744c00f7a6cecf1da9b30ae9ad51c566291ff1314e6cbbed8"}, - {file = "coverage-7.5.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:34d6d21d8795a97b14d503dcaf74226ae51eb1f2bd41015d3ef332a24d0a17b3"}, - {file = "coverage-7.5.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e317953bb4c074c06c798a11dbdd2cf9979dbcaa8ccc0fa4701d80042d4ebf1"}, - {file = "coverage-7.5.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:705f3d7c2b098c40f5b81790a5fedb274113373d4d1a69e65f8b68b0cc26f6db"}, - {file = "coverage-7.5.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1196e13c45e327d6cd0b6e471530a1882f1017eb83c6229fc613cd1a11b53cd"}, - {file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:015eddc5ccd5364dcb902eaecf9515636806fa1e0d5bef5769d06d0f31b54523"}, - {file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:fd27d8b49e574e50caa65196d908f80e4dff64d7e592d0c59788b45aad7e8b35"}, - {file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:33fc65740267222fc02975c061eb7167185fef4cc8f2770267ee8bf7d6a42f84"}, - {file = "coverage-7.5.3-cp312-cp312-win32.whl", hash = "sha256:7b2a19e13dfb5c8e145c7a6ea959485ee8e2204699903c88c7d25283584bfc08"}, - {file = "coverage-7.5.3-cp312-cp312-win_amd64.whl", hash = "sha256:0bbddc54bbacfc09b3edaec644d4ac90c08ee8ed4844b0f86227dcda2d428fcb"}, - {file = "coverage-7.5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f78300789a708ac1f17e134593f577407d52d0417305435b134805c4fb135adb"}, - {file = "coverage-7.5.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b368e1aee1b9b75757942d44d7598dcd22a9dbb126affcbba82d15917f0cc155"}, - {file = "coverage-7.5.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f836c174c3a7f639bded48ec913f348c4761cbf49de4a20a956d3431a7c9cb24"}, - {file = "coverage-7.5.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:244f509f126dc71369393ce5fea17c0592c40ee44e607b6d855e9c4ac57aac98"}, - {file = "coverage-7.5.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4c2872b3c91f9baa836147ca33650dc5c172e9273c808c3c3199c75490e709d"}, - {file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dd4b3355b01273a56b20c219e74e7549e14370b31a4ffe42706a8cda91f19f6d"}, - {file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f542287b1489c7a860d43a7d8883e27ca62ab84ca53c965d11dac1d3a1fab7ce"}, - {file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:75e3f4e86804023e991096b29e147e635f5e2568f77883a1e6eed74512659ab0"}, - {file = "coverage-7.5.3-cp38-cp38-win32.whl", hash = "sha256:c59d2ad092dc0551d9f79d9d44d005c945ba95832a6798f98f9216ede3d5f485"}, - {file = "coverage-7.5.3-cp38-cp38-win_amd64.whl", hash = "sha256:fa21a04112c59ad54f69d80e376f7f9d0f5f9123ab87ecd18fbb9ec3a2beed56"}, - {file = "coverage-7.5.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f5102a92855d518b0996eb197772f5ac2a527c0ec617124ad5242a3af5e25f85"}, - {file = "coverage-7.5.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d1da0a2e3b37b745a2b2a678a4c796462cf753aebf94edcc87dcc6b8641eae31"}, - {file = "coverage-7.5.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8383a6c8cefba1b7cecc0149415046b6fc38836295bc4c84e820872eb5478b3d"}, - {file = "coverage-7.5.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9aad68c3f2566dfae84bf46295a79e79d904e1c21ccfc66de88cd446f8686341"}, - {file = "coverage-7.5.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e079c9ec772fedbade9d7ebc36202a1d9ef7291bc9b3a024ca395c4d52853d7"}, - {file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bde997cac85fcac227b27d4fb2c7608a2c5f6558469b0eb704c5726ae49e1c52"}, - {file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:990fb20b32990b2ce2c5f974c3e738c9358b2735bc05075d50a6f36721b8f303"}, - {file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3d5a67f0da401e105753d474369ab034c7bae51a4c31c77d94030d59e41df5bd"}, - {file = "coverage-7.5.3-cp39-cp39-win32.whl", hash = "sha256:e08c470c2eb01977d221fd87495b44867a56d4d594f43739a8028f8646a51e0d"}, - {file = "coverage-7.5.3-cp39-cp39-win_amd64.whl", hash = "sha256:1d2a830ade66d3563bb61d1e3c77c8def97b30ed91e166c67d0632c018f380f0"}, - {file = "coverage-7.5.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:3538d8fb1ee9bdd2e2692b3b18c22bb1c19ffbefd06880f5ac496e42d7bb3884"}, - {file = "coverage-7.5.3.tar.gz", hash = "sha256:04aefca5190d1dc7a53a4c1a5a7f8568811306d7a8ee231c42fb69215571944f"}, + {file = "coverage-7.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dff044f661f59dace805eedb4a7404c573b6ff0cdba4a524141bc63d7be5c7fd"}, + {file = "coverage-7.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8659fd33ee9e6ca03950cfdcdf271d645cf681609153f218826dd9805ab585c"}, + {file = "coverage-7.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7792f0ab20df8071d669d929c75c97fecfa6bcab82c10ee4adb91c7a54055463"}, + {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4b3cd1ca7cd73d229487fa5caca9e4bc1f0bca96526b922d61053ea751fe791"}, + {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7e128f85c0b419907d1f38e616c4f1e9f1d1b37a7949f44df9a73d5da5cd53c"}, + {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a94925102c89247530ae1dab7dc02c690942566f22e189cbd53579b0693c0783"}, + {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dcd070b5b585b50e6617e8972f3fbbee786afca71b1936ac06257f7e178f00f6"}, + {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d50a252b23b9b4dfeefc1f663c568a221092cbaded20a05a11665d0dbec9b8fb"}, + {file = "coverage-7.6.0-cp310-cp310-win32.whl", hash = "sha256:0e7b27d04131c46e6894f23a4ae186a6a2207209a05df5b6ad4caee6d54a222c"}, + {file = "coverage-7.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dece71673b3187c86226c3ca793c5f891f9fc3d8aa183f2e3653da18566169"}, + {file = "coverage-7.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7b525ab52ce18c57ae232ba6f7010297a87ced82a2383b1afd238849c1ff933"}, + {file = "coverage-7.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bea27c4269234e06f621f3fac3925f56ff34bc14521484b8f66a580aacc2e7d"}, + {file = "coverage-7.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed8d1d1821ba5fc88d4a4f45387b65de52382fa3ef1f0115a4f7a20cdfab0e94"}, + {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1"}, + {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03cafe82c1b32b770a29fd6de923625ccac3185a54a5e66606da26d105f37dac"}, + {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d1b923fc4a40c5832be4f35a5dab0e5ff89cddf83bb4174499e02ea089daf57"}, + {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4b03741e70fb811d1a9a1d75355cf391f274ed85847f4b78e35459899f57af4d"}, + {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a73d18625f6a8a1cbb11eadc1d03929f9510f4131879288e3f7922097a429f63"}, + {file = "coverage-7.6.0-cp311-cp311-win32.whl", hash = "sha256:65fa405b837060db569a61ec368b74688f429b32fa47a8929a7a2f9b47183713"}, + {file = "coverage-7.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:6379688fb4cfa921ae349c76eb1a9ab26b65f32b03d46bb0eed841fd4cb6afb1"}, + {file = "coverage-7.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f7db0b6ae1f96ae41afe626095149ecd1b212b424626175a6633c2999eaad45b"}, + {file = "coverage-7.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bbdf9a72403110a3bdae77948b8011f644571311c2fb35ee15f0f10a8fc082e8"}, + {file = "coverage-7.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc44bf0315268e253bf563f3560e6c004efe38f76db03a1558274a6e04bf5d5"}, + {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da8549d17489cd52f85a9829d0e1d91059359b3c54a26f28bec2c5d369524807"}, + {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382"}, + {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fad32ee9b27350687035cb5fdf9145bc9cf0a094a9577d43e909948ebcfa27b"}, + {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:044a0985a4f25b335882b0966625270a8d9db3d3409ddc49a4eb00b0ef5e8cee"}, + {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:76d5f82213aa78098b9b964ea89de4617e70e0d43e97900c2778a50856dac605"}, + {file = "coverage-7.6.0-cp312-cp312-win32.whl", hash = "sha256:3c59105f8d58ce500f348c5b56163a4113a440dad6daa2294b5052a10db866da"}, + {file = "coverage-7.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:ca5d79cfdae420a1d52bf177de4bc2289c321d6c961ae321503b2ca59c17ae67"}, + {file = "coverage-7.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d39bd10f0ae453554798b125d2f39884290c480f56e8a02ba7a6ed552005243b"}, + {file = "coverage-7.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:beb08e8508e53a568811016e59f3234d29c2583f6b6e28572f0954a6b4f7e03d"}, + {file = "coverage-7.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2e16f4cd2bc4d88ba30ca2d3bbf2f21f00f382cf4e1ce3b1ddc96c634bc48ca"}, + {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6616d1c9bf1e3faea78711ee42a8b972367d82ceae233ec0ac61cc7fec09fa6b"}, + {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4567d6c334c46046d1c4c20024de2a1c3abc626817ae21ae3da600f5779b44"}, + {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d17c6a415d68cfe1091d3296ba5749d3d8696e42c37fca5d4860c5bf7b729f03"}, + {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9146579352d7b5f6412735d0f203bbd8d00113a680b66565e205bc605ef81bc6"}, + {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cdab02a0a941af190df8782aafc591ef3ad08824f97850b015c8c6a8b3877b0b"}, + {file = "coverage-7.6.0-cp38-cp38-win32.whl", hash = "sha256:df423f351b162a702c053d5dddc0fc0ef9a9e27ea3f449781ace5f906b664428"}, + {file = "coverage-7.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:f2501d60d7497fd55e391f423f965bbe9e650e9ffc3c627d5f0ac516026000b8"}, + {file = "coverage-7.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7221f9ac9dad9492cecab6f676b3eaf9185141539d5c9689d13fd6b0d7de840c"}, + {file = "coverage-7.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ddaaa91bfc4477d2871442bbf30a125e8fe6b05da8a0015507bfbf4718228ab2"}, + {file = "coverage-7.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4cbe651f3904e28f3a55d6f371203049034b4ddbce65a54527a3f189ca3b390"}, + {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:831b476d79408ab6ccfadaaf199906c833f02fdb32c9ab907b1d4aa0713cfa3b"}, + {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46c3d091059ad0b9c59d1034de74a7f36dcfa7f6d3bde782c49deb42438f2450"}, + {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4d5fae0a22dc86259dee66f2cc6c1d3e490c4a1214d7daa2a93d07491c5c04b6"}, + {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:07ed352205574aad067482e53dd606926afebcb5590653121063fbf4e2175166"}, + {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:49c76cdfa13015c4560702574bad67f0e15ca5a2872c6a125f6327ead2b731dd"}, + {file = "coverage-7.6.0-cp39-cp39-win32.whl", hash = "sha256:482855914928c8175735a2a59c8dc5806cf7d8f032e4820d52e845d1f731dca2"}, + {file = "coverage-7.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:543ef9179bc55edfd895154a51792b01c017c87af0ebaae092720152e19e42ca"}, + {file = "coverage-7.6.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:6fe885135c8a479d3e37a7aae61cbd3a0fb2deccb4dda3c25f92a49189f766d6"}, + {file = "coverage-7.6.0.tar.gz", hash = "sha256:289cc803fa1dc901f84701ac10c9ee873619320f2f9aff38794db4a4a0268d51"}, ] [package.extras] @@ -1186,33 +1197,33 @@ files = [ [[package]] name = "debugpy" -version = "1.8.1" +version = "1.8.2" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" files = [ - {file = "debugpy-1.8.1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:3bda0f1e943d386cc7a0e71bfa59f4137909e2ed947fb3946c506e113000f741"}, - {file = "debugpy-1.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dda73bf69ea479c8577a0448f8c707691152e6c4de7f0c4dec5a4bc11dee516e"}, - {file = "debugpy-1.8.1-cp310-cp310-win32.whl", hash = "sha256:3a79c6f62adef994b2dbe9fc2cc9cc3864a23575b6e387339ab739873bea53d0"}, - {file = "debugpy-1.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:7eb7bd2b56ea3bedb009616d9e2f64aab8fc7000d481faec3cd26c98a964bcdd"}, - {file = "debugpy-1.8.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:016a9fcfc2c6b57f939673c874310d8581d51a0fe0858e7fac4e240c5eb743cb"}, - {file = "debugpy-1.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd97ed11a4c7f6d042d320ce03d83b20c3fb40da892f994bc041bbc415d7a099"}, - {file = "debugpy-1.8.1-cp311-cp311-win32.whl", hash = "sha256:0de56aba8249c28a300bdb0672a9b94785074eb82eb672db66c8144fff673146"}, - {file = "debugpy-1.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:1a9fe0829c2b854757b4fd0a338d93bc17249a3bf69ecf765c61d4c522bb92a8"}, - {file = "debugpy-1.8.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3ebb70ba1a6524d19fa7bb122f44b74170c447d5746a503e36adc244a20ac539"}, - {file = "debugpy-1.8.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2e658a9630f27534e63922ebf655a6ab60c370f4d2fc5c02a5b19baf4410ace"}, - {file = "debugpy-1.8.1-cp312-cp312-win32.whl", hash = "sha256:caad2846e21188797a1f17fc09c31b84c7c3c23baf2516fed5b40b378515bbf0"}, - {file = "debugpy-1.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:edcc9f58ec0fd121a25bc950d4578df47428d72e1a0d66c07403b04eb93bcf98"}, - {file = "debugpy-1.8.1-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:7a3afa222f6fd3d9dfecd52729bc2e12c93e22a7491405a0ecbf9e1d32d45b39"}, - {file = "debugpy-1.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d915a18f0597ef685e88bb35e5d7ab968964b7befefe1aaea1eb5b2640b586c7"}, - {file = "debugpy-1.8.1-cp38-cp38-win32.whl", hash = "sha256:92116039b5500633cc8d44ecc187abe2dfa9b90f7a82bbf81d079fcdd506bae9"}, - {file = "debugpy-1.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:e38beb7992b5afd9d5244e96ad5fa9135e94993b0c551ceebf3fe1a5d9beb234"}, - {file = "debugpy-1.8.1-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:bfb20cb57486c8e4793d41996652e5a6a885b4d9175dd369045dad59eaacea42"}, - {file = "debugpy-1.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efd3fdd3f67a7e576dd869c184c5dd71d9aaa36ded271939da352880c012e703"}, - {file = "debugpy-1.8.1-cp39-cp39-win32.whl", hash = "sha256:58911e8521ca0c785ac7a0539f1e77e0ce2df753f786188f382229278b4cdf23"}, - {file = "debugpy-1.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:6df9aa9599eb05ca179fb0b810282255202a66835c6efb1d112d21ecb830ddd3"}, - {file = "debugpy-1.8.1-py2.py3-none-any.whl", hash = "sha256:28acbe2241222b87e255260c76741e1fbf04fdc3b6d094fcf57b6c6f75ce1242"}, - {file = "debugpy-1.8.1.zip", hash = "sha256:f696d6be15be87aef621917585f9bb94b1dc9e8aced570db1b8a6fc14e8f9b42"}, + {file = "debugpy-1.8.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:7ee2e1afbf44b138c005e4380097d92532e1001580853a7cb40ed84e0ef1c3d2"}, + {file = "debugpy-1.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f8c3f7c53130a070f0fc845a0f2cee8ed88d220d6b04595897b66605df1edd6"}, + {file = "debugpy-1.8.2-cp310-cp310-win32.whl", hash = "sha256:f179af1e1bd4c88b0b9f0fa153569b24f6b6f3de33f94703336363ae62f4bf47"}, + {file = "debugpy-1.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:0600faef1d0b8d0e85c816b8bb0cb90ed94fc611f308d5fde28cb8b3d2ff0fe3"}, + {file = "debugpy-1.8.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8a13417ccd5978a642e91fb79b871baded925d4fadd4dfafec1928196292aa0a"}, + {file = "debugpy-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acdf39855f65c48ac9667b2801234fc64d46778021efac2de7e50907ab90c634"}, + {file = "debugpy-1.8.2-cp311-cp311-win32.whl", hash = "sha256:2cbd4d9a2fc5e7f583ff9bf11f3b7d78dfda8401e8bb6856ad1ed190be4281ad"}, + {file = "debugpy-1.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:d3408fddd76414034c02880e891ea434e9a9cf3a69842098ef92f6e809d09afa"}, + {file = "debugpy-1.8.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:5d3ccd39e4021f2eb86b8d748a96c766058b39443c1f18b2dc52c10ac2757835"}, + {file = "debugpy-1.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62658aefe289598680193ff655ff3940e2a601765259b123dc7f89c0239b8cd3"}, + {file = "debugpy-1.8.2-cp312-cp312-win32.whl", hash = "sha256:bd11fe35d6fd3431f1546d94121322c0ac572e1bfb1f6be0e9b8655fb4ea941e"}, + {file = "debugpy-1.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:15bc2f4b0f5e99bf86c162c91a74c0631dbd9cef3c6a1d1329c946586255e859"}, + {file = "debugpy-1.8.2-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:5a019d4574afedc6ead1daa22736c530712465c0c4cd44f820d803d937531b2d"}, + {file = "debugpy-1.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40f062d6877d2e45b112c0bbade9a17aac507445fd638922b1a5434df34aed02"}, + {file = "debugpy-1.8.2-cp38-cp38-win32.whl", hash = "sha256:c78ba1680f1015c0ca7115671fe347b28b446081dada3fedf54138f44e4ba031"}, + {file = "debugpy-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:cf327316ae0c0e7dd81eb92d24ba8b5e88bb4d1b585b5c0d32929274a66a5210"}, + {file = "debugpy-1.8.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:1523bc551e28e15147815d1397afc150ac99dbd3a8e64641d53425dba57b0ff9"}, + {file = "debugpy-1.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e24ccb0cd6f8bfaec68d577cb49e9c680621c336f347479b3fce060ba7c09ec1"}, + {file = "debugpy-1.8.2-cp39-cp39-win32.whl", hash = "sha256:7f8d57a98c5a486c5c7824bc0b9f2f11189d08d73635c326abef268f83950326"}, + {file = "debugpy-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:16c8dcab02617b75697a0a925a62943e26a0330da076e2a10437edd9f0bf3755"}, + {file = "debugpy-1.8.2-py2.py3-none-any.whl", hash = "sha256:16e16df3a98a35c63c3ab1e4d19be4cbc7fdda92d9ddc059294f18910928e0ca"}, + {file = "debugpy-1.8.2.zip", hash = "sha256:95378ed08ed2089221896b9b3a8d021e642c24edc8fef20e5d4342ca8be65c00"}, ] [[package]] @@ -1253,17 +1264,18 @@ packaging = "*" [[package]] name = "dill" -version = "0.3.7" +version = "0.3.8" description = "serialize all of Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"}, - {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"}, + {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"}, + {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"}, ] [package.extras] graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] [[package]] name = "diskcache" @@ -1289,13 +1301,13 @@ files = [ [[package]] name = "dlt" -version = "0.4.12" +version = "0.5.1" description = "dlt is an open-source python-first scalable data loading library that does not require any backend to run." optional = false python-versions = "<3.13,>=3.8.1" files = [ - {file = "dlt-0.4.12-py3-none-any.whl", hash = "sha256:5d661731de05c1d76b00ce18a800269b3c01459b319c07dc48b4507df8013551"}, - {file = "dlt-0.4.12.tar.gz", hash = "sha256:0242581e3fd6ea81b9a676f8011018775c6a2985f76bd7474ab2cf98869e03ee"}, + {file = "dlt-0.5.1-py3-none-any.whl", hash = "sha256:19d7920816fadd049a1a92c4ecc4e740bf1cd5f6484fce535715f8c214a835ce"}, + {file = "dlt-0.5.1.tar.gz", hash = "sha256:dfa11e498feec3aca0022541850b6fa7dd3fddce4c2e6fef195530638269fec4"}, ] [package.dependencies] @@ -1308,7 +1320,7 @@ hexbytes = ">=0.2.2" humanize = ">=4.4.0" jsonpath-ng = ">=1.5.3" makefun = ">=1.15.0" -orjson = {version = ">=3.6.7,<=3.9.10", markers = "platform_python_implementation != \"PyPy\""} +orjson = {version = ">=3.6.7,<3.9.11 || >3.9.11,<3.9.12 || >3.9.12,<3.9.13 || >3.9.13,<3.9.14 || >3.9.14,<3.10.1 || >3.10.1,<4", markers = "platform_python_implementation != \"PyPy\""} packaging = ">=21.1" pathvalidate = ">=2.5.2" pendulum = ">=2.1.2" @@ -1331,22 +1343,23 @@ az = ["adlfs (>=2022.4.0)"] bigquery = ["gcsfs (>=2022.4.0)", "google-cloud-bigquery (>=2.26.0)", "grpcio (>=1.50.0)", "pyarrow (>=12.0.0)"] cli = ["cron-descriptor (>=1.2.32)", "pipdeptree (>=2.9.0,<2.10)"] clickhouse = ["adlfs (>=2022.4.0)", "clickhouse-connect (>=0.7.7)", "clickhouse-driver (>=0.2.7)", "gcsfs (>=2022.4.0)", "pyarrow (>=12.0.0)", "s3fs (>=2022.4.0)"] -databricks = ["databricks-sql-connector (>=2.9.3,<3.0.0)"] -dbt = ["dbt-athena-community (>=1.2.0)", "dbt-bigquery (>=1.2.0)", "dbt-core (>=1.2.0)", "dbt-databricks (>=1.7.3)", "dbt-duckdb (>=1.2.0)", "dbt-redshift (>=1.2.0)", "dbt-snowflake (>=1.2.0)"] +databricks = ["databricks-sql-connector (>=2.9.3)"] +deltalake = ["deltalake (>=0.17.4)", "pyarrow (>=12.0.0)"] dremio = ["pyarrow (>=12.0.0)"] duckdb = ["duckdb (>=0.6.1,<0.11)"] filesystem = ["botocore (>=1.28)", "s3fs (>=2022.4.0)"] gcp = ["gcsfs (>=2022.4.0)", "google-cloud-bigquery (>=2.26.0)", "grpcio (>=1.50.0)"] gs = ["gcsfs (>=2022.4.0)"] +lancedb = ["lancedb (>=0.8.2)", "pyarrow (>=12.0.0)"] motherduck = ["duckdb (>=0.6.1,<0.11)", "pyarrow (>=12.0.0)"] -mssql = ["pyodbc (>=4.0.39,<5.0.0)"] +mssql = ["pyodbc (>=4.0.39)"] parquet = ["pyarrow (>=12.0.0)"] postgres = ["psycopg2-binary (>=2.9.1)", "psycopg2cffi (>=2.9.0)"] -qdrant = ["qdrant-client[fastembed] (>=1.6.4,<2.0.0)"] +qdrant = ["qdrant-client[fastembed] (>=1.8)"] redshift = ["psycopg2-binary (>=2.9.1)", "psycopg2cffi (>=2.9.0)"] s3 = ["botocore (>=1.28)", "s3fs (>=2022.4.0)"] snowflake = ["snowflake-connector-python (>=3.5.0)"] -synapse = ["adlfs (>=2022.4.0)", "pyarrow (>=12.0.0)", "pyodbc (>=4.0.39,<5.0.0)"] +synapse = ["adlfs (>=2022.4.0)", "pyarrow (>=12.0.0)", "pyodbc (>=4.0.39)"] weaviate = ["weaviate-client (>=3.22)"] [[package]] @@ -1418,13 +1431,13 @@ files = [ [[package]] name = "duckdb-engine" -version = "0.12.1" +version = "0.13.0" description = "SQLAlchemy driver for duckdb" optional = false python-versions = "<4,>=3.8" files = [ - {file = "duckdb_engine-0.12.1-py3-none-any.whl", hash = "sha256:2449b61db4f7cf928ebbbb6b897a839bc3df353878533c1300818aa9094ee0e8"}, - {file = "duckdb_engine-0.12.1.tar.gz", hash = "sha256:8ee3b672f5d3abc85ea6290cde59a58a72462cdd671826db4b7d3d50d8ab49ba"}, + {file = "duckdb_engine-0.13.0-py3-none-any.whl", hash = "sha256:58ac839d6730d07c11148123aa16001623d780bcd7369eabc4bf1594b79ab0d0"}, + {file = "duckdb_engine-0.13.0.tar.gz", hash = "sha256:8e934091b2922a60c2faaac057f88b669fe4925cc26a3adaea8be7f27ca60bab"}, ] [package.dependencies] @@ -1434,13 +1447,13 @@ sqlalchemy = ">=1.3.22" [[package]] name = "exceptiongroup" -version = "1.2.1" +version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] [package.extras] @@ -1502,13 +1515,13 @@ tqdm = ">=4.66,<5.0" [[package]] name = "fastjsonschema" -version = "2.19.1" +version = "2.20.0" description = "Fastest Python implementation of JSON schema" optional = false python-versions = "*" files = [ - {file = "fastjsonschema-2.19.1-py3-none-any.whl", hash = "sha256:3672b47bc94178c9f23dbb654bf47440155d4db9df5f7bc47643315f9c405cd0"}, - {file = "fastjsonschema-2.19.1.tar.gz", hash = "sha256:e3126a94bdc4623d3de4485f8d468a12f02a67921315ddc87836d6e456dc789d"}, + {file = "fastjsonschema-2.20.0-py3-none-any.whl", hash = "sha256:5875f0b0fa7a0043a91e93a9b8f793bcbbba9691e7fd83dca95c28ba26d21f0a"}, + {file = "fastjsonschema-2.20.0.tar.gz", hash = "sha256:3d48fc5300ee96f5d116f10fe6f28d938e6008f59a6a025c2649475b87f76a23"}, ] [package.extras] @@ -1516,18 +1529,18 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc [[package]] name = "filelock" -version = "3.14.0" +version = "3.15.4" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, - {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, + {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"}, + {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"}, ] [package.extras] docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"] typing = ["typing-extensions (>=4.8)"] [[package]] @@ -1554,53 +1567,53 @@ files = [ [[package]] name = "fonttools" -version = "4.53.0" +version = "4.53.1" description = "Tools to manipulate font files" optional = false python-versions = ">=3.8" files = [ - {file = "fonttools-4.53.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:52a6e0a7a0bf611c19bc8ec8f7592bdae79c8296c70eb05917fd831354699b20"}, - {file = "fonttools-4.53.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:099634631b9dd271d4a835d2b2a9e042ccc94ecdf7e2dd9f7f34f7daf333358d"}, - {file = "fonttools-4.53.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e40013572bfb843d6794a3ce076c29ef4efd15937ab833f520117f8eccc84fd6"}, - {file = "fonttools-4.53.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:715b41c3e231f7334cbe79dfc698213dcb7211520ec7a3bc2ba20c8515e8a3b5"}, - {file = "fonttools-4.53.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74ae2441731a05b44d5988d3ac2cf784d3ee0a535dbed257cbfff4be8bb49eb9"}, - {file = "fonttools-4.53.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:95db0c6581a54b47c30860d013977b8a14febc206c8b5ff562f9fe32738a8aca"}, - {file = "fonttools-4.53.0-cp310-cp310-win32.whl", hash = "sha256:9cd7a6beec6495d1dffb1033d50a3f82dfece23e9eb3c20cd3c2444d27514068"}, - {file = "fonttools-4.53.0-cp310-cp310-win_amd64.whl", hash = "sha256:daaef7390e632283051e3cf3e16aff2b68b247e99aea916f64e578c0449c9c68"}, - {file = "fonttools-4.53.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a209d2e624ba492df4f3bfad5996d1f76f03069c6133c60cd04f9a9e715595ec"}, - {file = "fonttools-4.53.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4f520d9ac5b938e6494f58a25c77564beca7d0199ecf726e1bd3d56872c59749"}, - {file = "fonttools-4.53.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eceef49f457253000e6a2d0f7bd08ff4e9fe96ec4ffce2dbcb32e34d9c1b8161"}, - {file = "fonttools-4.53.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa1f3e34373aa16045484b4d9d352d4c6b5f9f77ac77a178252ccbc851e8b2ee"}, - {file = "fonttools-4.53.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:28d072169fe8275fb1a0d35e3233f6df36a7e8474e56cb790a7258ad822b6fd6"}, - {file = "fonttools-4.53.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4a2a6ba400d386e904fd05db81f73bee0008af37799a7586deaa4aef8cd5971e"}, - {file = "fonttools-4.53.0-cp311-cp311-win32.whl", hash = "sha256:bb7273789f69b565d88e97e9e1da602b4ee7ba733caf35a6c2affd4334d4f005"}, - {file = "fonttools-4.53.0-cp311-cp311-win_amd64.whl", hash = "sha256:9fe9096a60113e1d755e9e6bda15ef7e03391ee0554d22829aa506cdf946f796"}, - {file = "fonttools-4.53.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d8f191a17369bd53a5557a5ee4bab91d5330ca3aefcdf17fab9a497b0e7cff7a"}, - {file = "fonttools-4.53.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:93156dd7f90ae0a1b0e8871032a07ef3178f553f0c70c386025a808f3a63b1f4"}, - {file = "fonttools-4.53.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bff98816cb144fb7b85e4b5ba3888a33b56ecef075b0e95b95bcd0a5fbf20f06"}, - {file = "fonttools-4.53.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:973d030180eca8255b1bce6ffc09ef38a05dcec0e8320cc9b7bcaa65346f341d"}, - {file = "fonttools-4.53.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c4ee5a24e281fbd8261c6ab29faa7fd9a87a12e8c0eed485b705236c65999109"}, - {file = "fonttools-4.53.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bd5bc124fae781a4422f61b98d1d7faa47985f663a64770b78f13d2c072410c2"}, - {file = "fonttools-4.53.0-cp312-cp312-win32.whl", hash = "sha256:a239afa1126b6a619130909c8404070e2b473dd2b7fc4aacacd2e763f8597fea"}, - {file = "fonttools-4.53.0-cp312-cp312-win_amd64.whl", hash = "sha256:45b4afb069039f0366a43a5d454bc54eea942bfb66b3fc3e9a2c07ef4d617380"}, - {file = "fonttools-4.53.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:93bc9e5aaa06ff928d751dc6be889ff3e7d2aa393ab873bc7f6396a99f6fbb12"}, - {file = "fonttools-4.53.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2367d47816cc9783a28645bc1dac07f8ffc93e0f015e8c9fc674a5b76a6da6e4"}, - {file = "fonttools-4.53.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:907fa0b662dd8fc1d7c661b90782ce81afb510fc4b7aa6ae7304d6c094b27bce"}, - {file = "fonttools-4.53.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e0ad3c6ea4bd6a289d958a1eb922767233f00982cf0fe42b177657c86c80a8f"}, - {file = "fonttools-4.53.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:73121a9b7ff93ada888aaee3985a88495489cc027894458cb1a736660bdfb206"}, - {file = "fonttools-4.53.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ee595d7ba9bba130b2bec555a40aafa60c26ce68ed0cf509983e0f12d88674fd"}, - {file = "fonttools-4.53.0-cp38-cp38-win32.whl", hash = "sha256:fca66d9ff2ac89b03f5aa17e0b21a97c21f3491c46b583bb131eb32c7bab33af"}, - {file = "fonttools-4.53.0-cp38-cp38-win_amd64.whl", hash = "sha256:31f0e3147375002aae30696dd1dc596636abbd22fca09d2e730ecde0baad1d6b"}, - {file = "fonttools-4.53.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7d6166192dcd925c78a91d599b48960e0a46fe565391c79fe6de481ac44d20ac"}, - {file = "fonttools-4.53.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef50ec31649fbc3acf6afd261ed89d09eb909b97cc289d80476166df8438524d"}, - {file = "fonttools-4.53.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f193f060391a455920d61684a70017ef5284ccbe6023bb056e15e5ac3de11d1"}, - {file = "fonttools-4.53.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba9f09ff17f947392a855e3455a846f9855f6cf6bec33e9a427d3c1d254c712f"}, - {file = "fonttools-4.53.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0c555e039d268445172b909b1b6bdcba42ada1cf4a60e367d68702e3f87e5f64"}, - {file = "fonttools-4.53.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a4788036201c908079e89ae3f5399b33bf45b9ea4514913f4dbbe4fac08efe0"}, - {file = "fonttools-4.53.0-cp39-cp39-win32.whl", hash = "sha256:d1a24f51a3305362b94681120c508758a88f207fa0a681c16b5a4172e9e6c7a9"}, - {file = "fonttools-4.53.0-cp39-cp39-win_amd64.whl", hash = "sha256:1e677bfb2b4bd0e5e99e0f7283e65e47a9814b0486cb64a41adf9ef110e078f2"}, - {file = "fonttools-4.53.0-py3-none-any.whl", hash = "sha256:6b4f04b1fbc01a3569d63359f2227c89ab294550de277fd09d8fca6185669fa4"}, - {file = "fonttools-4.53.0.tar.gz", hash = "sha256:c93ed66d32de1559b6fc348838c7572d5c0ac1e4a258e76763a5caddd8944002"}, + {file = "fonttools-4.53.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0679a30b59d74b6242909945429dbddb08496935b82f91ea9bf6ad240ec23397"}, + {file = "fonttools-4.53.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8bf06b94694251861ba7fdeea15c8ec0967f84c3d4143ae9daf42bbc7717fe3"}, + {file = "fonttools-4.53.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b96cd370a61f4d083c9c0053bf634279b094308d52fdc2dd9a22d8372fdd590d"}, + {file = "fonttools-4.53.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1c7c5aa18dd3b17995898b4a9b5929d69ef6ae2af5b96d585ff4005033d82f0"}, + {file = "fonttools-4.53.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e013aae589c1c12505da64a7d8d023e584987e51e62006e1bb30d72f26522c41"}, + {file = "fonttools-4.53.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9efd176f874cb6402e607e4cc9b4a9cd584d82fc34a4b0c811970b32ba62501f"}, + {file = "fonttools-4.53.1-cp310-cp310-win32.whl", hash = "sha256:c8696544c964500aa9439efb6761947393b70b17ef4e82d73277413f291260a4"}, + {file = "fonttools-4.53.1-cp310-cp310-win_amd64.whl", hash = "sha256:8959a59de5af6d2bec27489e98ef25a397cfa1774b375d5787509c06659b3671"}, + {file = "fonttools-4.53.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1"}, + {file = "fonttools-4.53.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923"}, + {file = "fonttools-4.53.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719"}, + {file = "fonttools-4.53.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3"}, + {file = "fonttools-4.53.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6e08f572625a1ee682115223eabebc4c6a2035a6917eac6f60350aba297ccadb"}, + {file = "fonttools-4.53.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b21952c092ffd827504de7e66b62aba26fdb5f9d1e435c52477e6486e9d128b2"}, + {file = "fonttools-4.53.1-cp311-cp311-win32.whl", hash = "sha256:9dfdae43b7996af46ff9da520998a32b105c7f098aeea06b2226b30e74fbba88"}, + {file = "fonttools-4.53.1-cp311-cp311-win_amd64.whl", hash = "sha256:d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02"}, + {file = "fonttools-4.53.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d92d3c2a1b39631a6131c2fa25b5406855f97969b068e7e08413325bc0afba58"}, + {file = "fonttools-4.53.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3b3c8ebafbee8d9002bd8f1195d09ed2bd9ff134ddec37ee8f6a6375e6a4f0e8"}, + {file = "fonttools-4.53.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32f029c095ad66c425b0ee85553d0dc326d45d7059dbc227330fc29b43e8ba60"}, + {file = "fonttools-4.53.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f5e6c3510b79ea27bb1ebfcc67048cde9ec67afa87c7dd7efa5c700491ac7f"}, + {file = "fonttools-4.53.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f677ce218976496a587ab17140da141557beb91d2a5c1a14212c994093f2eae2"}, + {file = "fonttools-4.53.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9e6ceba2a01b448e36754983d376064730690401da1dd104ddb543519470a15f"}, + {file = "fonttools-4.53.1-cp312-cp312-win32.whl", hash = "sha256:791b31ebbc05197d7aa096bbc7bd76d591f05905d2fd908bf103af4488e60670"}, + {file = "fonttools-4.53.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ed170b5e17da0264b9f6fae86073be3db15fa1bd74061c8331022bca6d09bab"}, + {file = "fonttools-4.53.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c818c058404eb2bba05e728d38049438afd649e3c409796723dfc17cd3f08749"}, + {file = "fonttools-4.53.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:651390c3b26b0c7d1f4407cad281ee7a5a85a31a110cbac5269de72a51551ba2"}, + {file = "fonttools-4.53.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e54f1bba2f655924c1138bbc7fa91abd61f45c68bd65ab5ed985942712864bbb"}, + {file = "fonttools-4.53.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9cd19cf4fe0595ebdd1d4915882b9440c3a6d30b008f3cc7587c1da7b95be5f"}, + {file = "fonttools-4.53.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2af40ae9cdcb204fc1d8f26b190aa16534fcd4f0df756268df674a270eab575d"}, + {file = "fonttools-4.53.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:35250099b0cfb32d799fb5d6c651220a642fe2e3c7d2560490e6f1d3f9ae9169"}, + {file = "fonttools-4.53.1-cp38-cp38-win32.whl", hash = "sha256:f08df60fbd8d289152079a65da4e66a447efc1d5d5a4d3f299cdd39e3b2e4a7d"}, + {file = "fonttools-4.53.1-cp38-cp38-win_amd64.whl", hash = "sha256:7b6b35e52ddc8fb0db562133894e6ef5b4e54e1283dff606fda3eed938c36fc8"}, + {file = "fonttools-4.53.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75a157d8d26c06e64ace9df037ee93a4938a4606a38cb7ffaf6635e60e253b7a"}, + {file = "fonttools-4.53.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4824c198f714ab5559c5be10fd1adf876712aa7989882a4ec887bf1ef3e00e31"}, + {file = "fonttools-4.53.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:becc5d7cb89c7b7afa8321b6bb3dbee0eec2b57855c90b3e9bf5fb816671fa7c"}, + {file = "fonttools-4.53.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84ec3fb43befb54be490147b4a922b5314e16372a643004f182babee9f9c3407"}, + {file = "fonttools-4.53.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:73379d3ffdeecb376640cd8ed03e9d2d0e568c9d1a4e9b16504a834ebadc2dfb"}, + {file = "fonttools-4.53.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:02569e9a810f9d11f4ae82c391ebc6fb5730d95a0657d24d754ed7763fb2d122"}, + {file = "fonttools-4.53.1-cp39-cp39-win32.whl", hash = "sha256:aae7bd54187e8bf7fd69f8ab87b2885253d3575163ad4d669a262fe97f0136cb"}, + {file = "fonttools-4.53.1-cp39-cp39-win_amd64.whl", hash = "sha256:e5b708073ea3d684235648786f5f6153a48dc8762cdfe5563c57e80787c29fbb"}, + {file = "fonttools-4.53.1-py3-none-any.whl", hash = "sha256:f1f8758a2ad110bd6432203a344269f445a2907dc24ef6bccfd0ac4e14e0d71d"}, + {file = "fonttools-4.53.1.tar.gz", hash = "sha256:e128778a8e9bc11159ce5447f76766cefbd876f44bd79aff030287254e4752c4"}, ] [package.extras] @@ -1716,13 +1729,13 @@ files = [ [[package]] name = "fsspec" -version = "2023.10.0" +version = "2024.6.1" description = "File-system specification" optional = false python-versions = ">=3.8" files = [ - {file = "fsspec-2023.10.0-py3-none-any.whl", hash = "sha256:346a8f024efeb749d2a5fca7ba8854474b1ff9af7c3faaf636a4548781136529"}, - {file = "fsspec-2023.10.0.tar.gz", hash = "sha256:330c66757591df346ad3091a53bd907e15348c2ba17d63fd54f5c39c4457d2a5"}, + {file = "fsspec-2024.6.1-py3-none-any.whl", hash = "sha256:3cb443f8bcd2efb31295a5b9fdb02aee81d8452c80d28f97a6d0959e6cee101e"}, + {file = "fsspec-2024.6.1.tar.gz", hash = "sha256:fad7d7e209dd4c1208e3bbfda706620e0da5142bebbd9c384afb95b07e798e49"}, ] [package.extras] @@ -1730,7 +1743,8 @@ abfs = ["adlfs"] adl = ["adlfs"] arrow = ["pyarrow (>=1)"] dask = ["dask", "distributed"] -devel = ["pytest", "pytest-cov"] +dev = ["pre-commit", "ruff"] +doc = ["numpydoc", "sphinx", "sphinx-design", "sphinx-rtd-theme", "yarl"] dropbox = ["dropbox", "dropboxdrivefs", "requests"] full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] fuse = ["fusepy"] @@ -1740,13 +1754,16 @@ github = ["requests"] gs = ["gcsfs"] gui = ["panel"] hdfs = ["pyarrow (>=1)"] -http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "requests"] +http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)"] libarchive = ["libarchive-c"] oci = ["ocifs"] s3 = ["s3fs"] sftp = ["paramiko"] smb = ["smbprotocol"] ssh = ["paramiko"] +test = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "numpy", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "requests"] +test-downstream = ["aiobotocore (>=2.5.4,<3.0.0)", "dask-expr", "dask[dataframe,test]", "moto[server] (>4,<5)", "pytest-timeout", "xarray"] +test-full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "cloudpickle", "dask", "distributed", "dropbox", "dropboxdrivefs", "fastparquet", "fusepy", "gcsfs", "jinja2", "kerchunk", "libarchive-c", "lz4", "notebook", "numpy", "ocifs", "pandas", "panel", "paramiko", "pyarrow", "pyarrow (>=1)", "pyftpdlib", "pygit2", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "python-snappy", "requests", "smbprotocol", "tqdm", "urllib3", "zarr", "zstandard"] tqdm = ["tqdm"] [[package]] @@ -1811,13 +1828,13 @@ files = [ [[package]] name = "graphistry" -version = "0.33.8" +version = "0.33.9" description = "A visual graph analytics library for extracting, transforming, displaying, and sharing big graphs with end-to-end GPU acceleration" optional = false python-versions = ">=3.7" files = [ - {file = "graphistry-0.33.8-py3-none-any.whl", hash = "sha256:2fdc4418603c24b203fa97b5e40694888a9403e2d98659edb838a1d90ed00feb"}, - {file = "graphistry-0.33.8.tar.gz", hash = "sha256:1d9ff9fa8b51023c8b8c9af3ba10349ab1bc637c90868b27135bf706b1530e4d"}, + {file = "graphistry-0.33.9-py3-none-any.whl", hash = "sha256:6952d96a0dfd77d7b7498f93a4986ea2189cb62553d4a27df18f02106ea4db99"}, + {file = "graphistry-0.33.9.tar.gz", hash = "sha256:40c095ae0ad4143d686b3802495c643a3decb4d663e0038aa6645c06c95d4d0b"}, ] [package.dependencies] @@ -1920,16 +1937,17 @@ test = ["objgraph", "psutil"] [[package]] name = "griffe" -version = "0.45.3" +version = "0.48.0" description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." optional = false python-versions = ">=3.8" files = [ - {file = "griffe-0.45.3-py3-none-any.whl", hash = "sha256:ed1481a680ae3e28f91a06e0d8a51a5c9b97555aa2527abc2664447cc22337d6"}, - {file = "griffe-0.45.3.tar.gz", hash = "sha256:02ee71cc1a5035864b97bd0dbfff65c33f6f2c8854d3bd48a791905c2b8a44b9"}, + {file = "griffe-0.48.0-py3-none-any.whl", hash = "sha256:f944c6ff7bd31cf76f264adcd6ab8f3d00a2f972ae5cc8db2d7b6dcffeff65a2"}, + {file = "griffe-0.48.0.tar.gz", hash = "sha256:f099461c02f016b6be4af386d5aa92b01fb4efe6c1c2c360dda9a5d0a863bb7f"}, ] [package.dependencies] +backports-strenum = {version = ">=1.3", markers = "python_version < \"3.11\""} colorama = ">=0.4" [[package]] @@ -1953,61 +1971,61 @@ typing-extensions = ">=4.7,<5" [[package]] name = "grpcio" -version = "1.64.1" +version = "1.65.1" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.8" files = [ - {file = "grpcio-1.64.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:55697ecec192bc3f2f3cc13a295ab670f51de29884ca9ae6cd6247df55df2502"}, - {file = "grpcio-1.64.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:3b64ae304c175671efdaa7ec9ae2cc36996b681eb63ca39c464958396697daff"}, - {file = "grpcio-1.64.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:bac71b4b28bc9af61efcdc7630b166440bbfbaa80940c9a697271b5e1dabbc61"}, - {file = "grpcio-1.64.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c024ffc22d6dc59000faf8ad781696d81e8e38f4078cb0f2630b4a3cf231a90"}, - {file = "grpcio-1.64.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7cd5c1325f6808b8ae31657d281aadb2a51ac11ab081ae335f4f7fc44c1721d"}, - {file = "grpcio-1.64.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0a2813093ddb27418a4c99f9b1c223fab0b053157176a64cc9db0f4557b69bd9"}, - {file = "grpcio-1.64.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2981c7365a9353f9b5c864595c510c983251b1ab403e05b1ccc70a3d9541a73b"}, - {file = "grpcio-1.64.1-cp310-cp310-win32.whl", hash = "sha256:1262402af5a511c245c3ae918167eca57342c72320dffae5d9b51840c4b2f86d"}, - {file = "grpcio-1.64.1-cp310-cp310-win_amd64.whl", hash = "sha256:19264fc964576ddb065368cae953f8d0514ecc6cb3da8903766d9fb9d4554c33"}, - {file = "grpcio-1.64.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:58b1041e7c870bb30ee41d3090cbd6f0851f30ae4eb68228955d973d3efa2e61"}, - {file = "grpcio-1.64.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bbc5b1d78a7822b0a84c6f8917faa986c1a744e65d762ef6d8be9d75677af2ca"}, - {file = "grpcio-1.64.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:5841dd1f284bd1b3d8a6eca3a7f062b06f1eec09b184397e1d1d43447e89a7ae"}, - {file = "grpcio-1.64.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8caee47e970b92b3dd948371230fcceb80d3f2277b3bf7fbd7c0564e7d39068e"}, - {file = "grpcio-1.64.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73819689c169417a4f978e562d24f2def2be75739c4bed1992435d007819da1b"}, - {file = "grpcio-1.64.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6503b64c8b2dfad299749cad1b595c650c91e5b2c8a1b775380fcf8d2cbba1e9"}, - {file = "grpcio-1.64.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1de403fc1305fd96cfa75e83be3dee8538f2413a6b1685b8452301c7ba33c294"}, - {file = "grpcio-1.64.1-cp311-cp311-win32.whl", hash = "sha256:d4d29cc612e1332237877dfa7fe687157973aab1d63bd0f84cf06692f04c0367"}, - {file = "grpcio-1.64.1-cp311-cp311-win_amd64.whl", hash = "sha256:5e56462b05a6f860b72f0fa50dca06d5b26543a4e88d0396259a07dc30f4e5aa"}, - {file = "grpcio-1.64.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:4657d24c8063e6095f850b68f2d1ba3b39f2b287a38242dcabc166453e950c59"}, - {file = "grpcio-1.64.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:62b4e6eb7bf901719fce0ca83e3ed474ae5022bb3827b0a501e056458c51c0a1"}, - {file = "grpcio-1.64.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:ee73a2f5ca4ba44fa33b4d7d2c71e2c8a9e9f78d53f6507ad68e7d2ad5f64a22"}, - {file = "grpcio-1.64.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:198908f9b22e2672a998870355e226a725aeab327ac4e6ff3a1399792ece4762"}, - {file = "grpcio-1.64.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39b9d0acaa8d835a6566c640f48b50054f422d03e77e49716d4c4e8e279665a1"}, - {file = "grpcio-1.64.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:5e42634a989c3aa6049f132266faf6b949ec2a6f7d302dbb5c15395b77d757eb"}, - {file = "grpcio-1.64.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b1a82e0b9b3022799c336e1fc0f6210adc019ae84efb7321d668129d28ee1efb"}, - {file = "grpcio-1.64.1-cp312-cp312-win32.whl", hash = "sha256:55260032b95c49bee69a423c2f5365baa9369d2f7d233e933564d8a47b893027"}, - {file = "grpcio-1.64.1-cp312-cp312-win_amd64.whl", hash = "sha256:c1a786ac592b47573a5bb7e35665c08064a5d77ab88a076eec11f8ae86b3e3f6"}, - {file = "grpcio-1.64.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:a011ac6c03cfe162ff2b727bcb530567826cec85eb8d4ad2bfb4bd023287a52d"}, - {file = "grpcio-1.64.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:4d6dab6124225496010bd22690f2d9bd35c7cbb267b3f14e7a3eb05c911325d4"}, - {file = "grpcio-1.64.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:a5e771d0252e871ce194d0fdcafd13971f1aae0ddacc5f25615030d5df55c3a2"}, - {file = "grpcio-1.64.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c3c1b90ab93fed424e454e93c0ed0b9d552bdf1b0929712b094f5ecfe7a23ad"}, - {file = "grpcio-1.64.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20405cb8b13fd779135df23fabadc53b86522d0f1cba8cca0e87968587f50650"}, - {file = "grpcio-1.64.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0cc79c982ccb2feec8aad0e8fb0d168bcbca85bc77b080d0d3c5f2f15c24ea8f"}, - {file = "grpcio-1.64.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a3a035c37ce7565b8f4f35ff683a4db34d24e53dc487e47438e434eb3f701b2a"}, - {file = "grpcio-1.64.1-cp38-cp38-win32.whl", hash = "sha256:1257b76748612aca0f89beec7fa0615727fd6f2a1ad580a9638816a4b2eb18fd"}, - {file = "grpcio-1.64.1-cp38-cp38-win_amd64.whl", hash = "sha256:0a12ddb1678ebc6a84ec6b0487feac020ee2b1659cbe69b80f06dbffdb249122"}, - {file = "grpcio-1.64.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:75dbbf415026d2862192fe1b28d71f209e2fd87079d98470db90bebe57b33179"}, - {file = "grpcio-1.64.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e3d9f8d1221baa0ced7ec7322a981e28deb23749c76eeeb3d33e18b72935ab62"}, - {file = "grpcio-1.64.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:5f8b75f64d5d324c565b263c67dbe4f0af595635bbdd93bb1a88189fc62ed2e5"}, - {file = "grpcio-1.64.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c84ad903d0d94311a2b7eea608da163dace97c5fe9412ea311e72c3684925602"}, - {file = "grpcio-1.64.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:940e3ec884520155f68a3b712d045e077d61c520a195d1a5932c531f11883489"}, - {file = "grpcio-1.64.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f10193c69fc9d3d726e83bbf0f3d316f1847c3071c8c93d8090cf5f326b14309"}, - {file = "grpcio-1.64.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ac15b6c2c80a4d1338b04d42a02d376a53395ddf0ec9ab157cbaf44191f3ffdd"}, - {file = "grpcio-1.64.1-cp39-cp39-win32.whl", hash = "sha256:03b43d0ccf99c557ec671c7dede64f023c7da9bb632ac65dbc57f166e4970040"}, - {file = "grpcio-1.64.1-cp39-cp39-win_amd64.whl", hash = "sha256:ed6091fa0adcc7e4ff944090cf203a52da35c37a130efa564ded02b7aff63bcd"}, - {file = "grpcio-1.64.1.tar.gz", hash = "sha256:8d51dd1c59d5fa0f34266b80a3805ec29a1f26425c2a54736133f6d87fc4968a"}, + {file = "grpcio-1.65.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:3dc5f928815b8972fb83b78d8db5039559f39e004ec93ebac316403fe031a062"}, + {file = "grpcio-1.65.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:8333ca46053c35484c9f2f7e8d8ec98c1383a8675a449163cea31a2076d93de8"}, + {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:7af64838b6e615fff0ec711960ed9b6ee83086edfa8c32670eafb736f169d719"}, + {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbb64b4166362d9326f7efbf75b1c72106c1aa87f13a8c8b56a1224fac152f5c"}, + {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8422dc13ad93ec8caa2612b5032a2b9cd6421c13ed87f54db4a3a2c93afaf77"}, + {file = "grpcio-1.65.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4effc0562b6c65d4add6a873ca132e46ba5e5a46f07c93502c37a9ae7f043857"}, + {file = "grpcio-1.65.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a6c71575a2fedf259724981fd73a18906513d2f306169c46262a5bae956e6364"}, + {file = "grpcio-1.65.1-cp310-cp310-win32.whl", hash = "sha256:34966cf526ef0ea616e008d40d989463e3db157abb213b2f20c6ce0ae7928875"}, + {file = "grpcio-1.65.1-cp310-cp310-win_amd64.whl", hash = "sha256:ca931de5dd6d9eb94ff19a2c9434b23923bce6f767179fef04dfa991f282eaad"}, + {file = "grpcio-1.65.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:bbb46330cc643ecf10bd9bd4ca8e7419a14b6b9dedd05f671c90fb2c813c6037"}, + {file = "grpcio-1.65.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d827a6fb9215b961eb73459ad7977edb9e748b23e3407d21c845d1d8ef6597e5"}, + {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:6e71aed8835f8d9fbcb84babc93a9da95955d1685021cceb7089f4f1e717d719"}, + {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a1c84560b3b2d34695c9ba53ab0264e2802721c530678a8f0a227951f453462"}, + {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27adee2338d697e71143ed147fe286c05810965d5d30ec14dd09c22479bfe48a"}, + {file = "grpcio-1.65.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f62652ddcadc75d0e7aa629e96bb61658f85a993e748333715b4ab667192e4e8"}, + {file = "grpcio-1.65.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:71a05fd814700dd9cb7d9a507f2f6a1ef85866733ccaf557eedacec32d65e4c2"}, + {file = "grpcio-1.65.1-cp311-cp311-win32.whl", hash = "sha256:b590f1ad056294dfaeac0b7e1b71d3d5ace638d8dd1f1147ce4bd13458783ba8"}, + {file = "grpcio-1.65.1-cp311-cp311-win_amd64.whl", hash = "sha256:12e9bdf3b5fd48e5fbe5b3da382ad8f97c08b47969f3cca81dd9b36b86ed39e2"}, + {file = "grpcio-1.65.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:54cb822e177374b318b233e54b6856c692c24cdbd5a3ba5335f18a47396bac8f"}, + {file = "grpcio-1.65.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:aaf3c54419a28d45bd1681372029f40e5bfb58e5265e3882eaf21e4a5f81a119"}, + {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:557de35bdfbe8bafea0a003dbd0f4da6d89223ac6c4c7549d78e20f92ead95d9"}, + {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8bfd95ef3b097f0cc86ade54eafefa1c8ed623aa01a26fbbdcd1a3650494dd11"}, + {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e6a8f3d6c41e6b642870afe6cafbaf7b61c57317f9ec66d0efdaf19db992b90"}, + {file = "grpcio-1.65.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1faaf7355ceed07ceaef0b9dcefa4c98daf1dd8840ed75c2de128c3f4a4d859d"}, + {file = "grpcio-1.65.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:60f1f38eed830488ad2a1b11579ef0f345ff16fffdad1d24d9fbc97ba31804ff"}, + {file = "grpcio-1.65.1-cp312-cp312-win32.whl", hash = "sha256:e75acfa52daf5ea0712e8aa82f0003bba964de7ae22c26d208cbd7bc08500177"}, + {file = "grpcio-1.65.1-cp312-cp312-win_amd64.whl", hash = "sha256:ff5a84907e51924973aa05ed8759210d8cdae7ffcf9e44fd17646cf4a902df59"}, + {file = "grpcio-1.65.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:1fbd6331f18c3acd7e09d17fd840c096f56eaf0ef830fbd50af45ae9dc8dfd83"}, + {file = "grpcio-1.65.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:de5b6be29116e094c5ef9d9e4252e7eb143e3d5f6bd6d50a78075553ab4930b0"}, + {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:e4a3cdba62b2d6aeae6027ae65f350de6dc082b72e6215eccf82628e79efe9ba"}, + {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:941c4869aa229d88706b78187d60d66aca77fe5c32518b79e3c3e03fc26109a2"}, + {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f40cebe5edb518d78b8131e87cb83b3ee688984de38a232024b9b44e74ee53d3"}, + {file = "grpcio-1.65.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2ca684ba331fb249d8a1ce88db5394e70dbcd96e58d8c4b7e0d7b141a453dce9"}, + {file = "grpcio-1.65.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8558f0083ddaf5de64a59c790bffd7568e353914c0c551eae2955f54ee4b857f"}, + {file = "grpcio-1.65.1-cp38-cp38-win32.whl", hash = "sha256:8d8143a3e3966f85dce6c5cc45387ec36552174ba5712c5dc6fcc0898fb324c0"}, + {file = "grpcio-1.65.1-cp38-cp38-win_amd64.whl", hash = "sha256:76e81a86424d6ca1ce7c16b15bdd6a964a42b40544bf796a48da241fdaf61153"}, + {file = "grpcio-1.65.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:cb5175f45c980ff418998723ea1b3869cce3766d2ab4e4916fbd3cedbc9d0ed3"}, + {file = "grpcio-1.65.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b12c1aa7b95abe73b3e04e052c8b362655b41c7798da69f1eaf8d186c7d204df"}, + {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:3019fb50128b21a5e018d89569ffaaaa361680e1346c2f261bb84a91082eb3d3"}, + {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ae15275ed98ea267f64ee9ddedf8ecd5306a5b5bb87972a48bfe24af24153e8"}, + {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f096ffb881f37e8d4f958b63c74bfc400c7cebd7a944b027357cd2fb8d91a57"}, + {file = "grpcio-1.65.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2f56b5a68fdcf17a0a1d524bf177218c3c69b3947cb239ea222c6f1867c3ab68"}, + {file = "grpcio-1.65.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:941596d419b9736ab548aa0feb5bbba922f98872668847bf0720b42d1d227b9e"}, + {file = "grpcio-1.65.1-cp39-cp39-win32.whl", hash = "sha256:5fd7337a823b890215f07d429f4f193d24b80d62a5485cf88ee06648591a0c57"}, + {file = "grpcio-1.65.1-cp39-cp39-win_amd64.whl", hash = "sha256:1bceeec568372cbebf554eae1b436b06c2ff24cfaf04afade729fb9035408c6c"}, + {file = "grpcio-1.65.1.tar.gz", hash = "sha256:3c492301988cd720cd145d84e17318d45af342e29ef93141228f9cd73222368b"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.64.1)"] +protobuf = ["grpcio-tools (>=1.65.1)"] [[package]] name = "grpcio-health-checking" @@ -2140,17 +2158,17 @@ hyperframe = ">=6.0,<7" [[package]] name = "hexbytes" -version = "1.2.0" +version = "1.2.1" description = "hexbytes: Python `bytes` subclass that decodes hex, with a readable console output" optional = false -python-versions = ">=3.8, <4" +python-versions = "<4,>=3.8" files = [ - {file = "hexbytes-1.2.0-py3-none-any.whl", hash = "sha256:bb243ab58b8d8390e3a753fbc9e3616f0f958df43d874e19ae0e4b746722a7e9"}, - {file = "hexbytes-1.2.0.tar.gz", hash = "sha256:965f1cc712e7b263c41fdf3fb36cf671ba6f59b895937cf33941a5c996ec3a5c"}, + {file = "hexbytes-1.2.1-py3-none-any.whl", hash = "sha256:e64890b203a31f4a23ef11470ecfcca565beaee9198df623047df322b757471a"}, + {file = "hexbytes-1.2.1.tar.gz", hash = "sha256:515f00dddf31053db4d0d7636dd16061c1d896c3109b8e751005db4ca46bcca7"}, ] [package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-utils (>=2.0.0)", "hypothesis (>=3.44.24,<=6.31.6)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +dev = ["build (>=0.9.0)", "bump-my-version (>=0.19.0)", "eth-utils (>=2.0.0)", "hypothesis (>=3.44.24,<=6.31.6)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] test = ["eth-utils (>=2.0.0)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] @@ -2269,13 +2287,13 @@ pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_ve [[package]] name = "humanize" -version = "4.9.0" +version = "4.10.0" description = "Python humanize utilities" optional = false python-versions = ">=3.8" files = [ - {file = "humanize-4.9.0-py3-none-any.whl", hash = "sha256:ce284a76d5b1377fd8836733b983bfb0b76f1aa1c090de2566fcf008d7f6ab16"}, - {file = "humanize-4.9.0.tar.gz", hash = "sha256:582a265c931c683a7e9b8ed9559089dea7edcf6cc95be39a3cbc2c5d5ac2bcfa"}, + {file = "humanize-4.10.0-py3-none-any.whl", hash = "sha256:39e7ccb96923e732b5c2e27aeaa3b10a8dfeeba3eb965ba7b74a3eb0e30040a6"}, + {file = "humanize-4.10.0.tar.gz", hash = "sha256:06b6eb0293e4b85e8d385397c5868926820db32b9b654b932f57fa41c23c9978"}, ] [package.extras] @@ -2353,40 +2371,59 @@ files = [ [[package]] name = "instructor" -version = "1.2.1" +version = "1.3.5" description = "structured outputs for llm" optional = false python-versions = "<4.0,>=3.9" files = [ - {file = "instructor-1.2.1-py3-none-any.whl", hash = "sha256:09b7f7ec84780816d64f5080febb982210ce752094f97ddd12058f76695561b7"}, - {file = "instructor-1.2.1.tar.gz", hash = "sha256:34fed99480352723b8295258d75444a3487f46d8e1fb9f06474a125ae2789318"}, + {file = "instructor-1.3.5-py3-none-any.whl", hash = "sha256:067372a6bbecf6617720365f1afdc100fecba679b0e152a00918442c2e3375ff"}, + {file = "instructor-1.3.5.tar.gz", hash = "sha256:fe725db5b4b32ca08ca1e820e699cf871b52cb3385b95de37ffb97d5b0a49c18"}, ] [package.dependencies] aiohttp = ">=3.9.1,<4.0.0" docstring-parser = ">=0.16,<0.17" +jiter = ">=0.4.1,<0.5.0" openai = ">=1.1.0,<2.0.0" -pydantic = "2.7.0" +pydantic = ">=2.8.0,<3.0.0" pydantic-core = ">=2.18.0,<3.0.0" rich = ">=13.7.0,<14.0.0" -tenacity = ">=8.2.3,<9.0.0" +tenacity = ">=8.4.1,<9.0.0" typer = ">=0.9.0,<1.0.0" [package.extras] -anthropic = ["anthropic (>=0.23.1,<0.24.0)", "xmltodict (>=0.13.0,<0.14.0)"] +anthropic = ["anthropic (>=0.27.0,<0.28.0)", "xmltodict (>=0.13.0,<0.14.0)"] cohere = ["cohere (>=5.1.8,<6.0.0)"] +google-generativeai = ["google-generativeai (>=0.5.4,<0.6.0)"] groq = ["groq (>=0.4.2,<0.5.0)"] -test-docs = ["anthropic (>=0.23.1,<0.24.0)", "cohere (>=5.1.8,<6.0.0)", "diskcache (>=5.6.3,<6.0.0)", "fastapi (>=0.109.2,<0.110.0)", "groq (>=0.4.2,<0.5.0)", "litellm (>=1.0.0,<2.0.0)", "pandas (>=2.2.0,<3.0.0)", "pydantic_extra_types (>=2.6.0,<3.0.0)", "redis (>=5.0.1,<6.0.0)", "tabulate (>=0.9.0,<0.10.0)"] +litellm = ["litellm (>=1.35.31,<2.0.0)"] +mistralai = ["mistralai (>=0.1.8,<0.2.0)"] +test-docs = ["anthropic (>=0.27.0,<0.28.0)", "cohere (>=5.1.8,<6.0.0)", "diskcache (>=5.6.3,<6.0.0)", "fastapi (>=0.109.2,<0.110.0)", "groq (>=0.4.2,<0.5.0)", "litellm (>=1.35.31,<2.0.0)", "mistralai (>=0.1.8,<0.2.0)", "pandas (>=2.2.0,<3.0.0)", "pydantic_extra_types (>=2.6.0,<3.0.0)", "redis (>=5.0.1,<6.0.0)", "tabulate (>=0.9.0,<0.10.0)"] +vertexai = ["google-cloud-aiplatform (>=1.53.0,<2.0.0)", "jsonref (>=1.1.0,<2.0.0)"] + +[[package]] +name = "intel-openmp" +version = "2021.4.0" +description = "Intel OpenMP* Runtime Library" +optional = false +python-versions = "*" +files = [ + {file = "intel_openmp-2021.4.0-py2.py3-none-macosx_10_15_x86_64.macosx_11_0_x86_64.whl", hash = "sha256:41c01e266a7fdb631a7609191709322da2bbf24b252ba763f125dd651bcc7675"}, + {file = "intel_openmp-2021.4.0-py2.py3-none-manylinux1_i686.whl", hash = "sha256:3b921236a38384e2016f0f3d65af6732cf2c12918087128a9163225451e776f2"}, + {file = "intel_openmp-2021.4.0-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:e2240ab8d01472fed04f3544a878cda5da16c26232b7ea1b59132dbfb48b186e"}, + {file = "intel_openmp-2021.4.0-py2.py3-none-win32.whl", hash = "sha256:6e863d8fd3d7e8ef389d52cf97a50fe2afe1a19247e8c0d168ce021546f96fc9"}, + {file = "intel_openmp-2021.4.0-py2.py3-none-win_amd64.whl", hash = "sha256:eef4c8bcc8acefd7f5cd3b9384dbf73d59e2c99fc56545712ded913f43c4a94f"}, +] [[package]] name = "ipykernel" -version = "6.29.4" +version = "6.29.5" description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.8" files = [ - {file = "ipykernel-6.29.4-py3-none-any.whl", hash = "sha256:1181e653d95c6808039c509ef8e67c4126b3b3af7781496c7cbfb5ed938a27da"}, - {file = "ipykernel-6.29.4.tar.gz", hash = "sha256:3d44070060f9475ac2092b760123fadf105d2e2493c24848b6691a7c4f42af5c"}, + {file = "ipykernel-6.29.5-py3-none-any.whl", hash = "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5"}, + {file = "ipykernel-6.29.5.tar.gz", hash = "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215"}, ] [package.dependencies] @@ -2495,6 +2532,88 @@ docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alab qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] +[[package]] +name = "jellyfish" +version = "1.0.4" +description = "Approximate and phonetic matching of strings." +optional = false +python-versions = ">=3.7" +files = [ + {file = "jellyfish-1.0.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f2cfa648575d1e8197cd61a1936929913916173aee8ee66210eb6a08b1a2fa11"}, + {file = "jellyfish-1.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3c915ce23a518d2289c63a502064bf970b9748d9e4164e21e36ebba40c07ad37"}, + {file = "jellyfish-1.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a001b0794aa84bcab311f6019289904ddf417b47ffe2b4796b41a8314bae3c1c"}, + {file = "jellyfish-1.0.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ffe094f4d5b1de72ed1e8bb3e729ada8915f096bc04c344aabb4327a669f272e"}, + {file = "jellyfish-1.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:481689f6e1a695ddf44b7fe9250d0f86839d98ab5418115d8e52886d488fd259"}, + {file = "jellyfish-1.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:30ccf4b1e6a6f9a54f60250f5d65898746186b93aceebfd0dc7159cbe5554db3"}, + {file = "jellyfish-1.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0459f8dc1d63a165f3848ed9f756107cff0d4990e3dffbaed839228073b628b7"}, + {file = "jellyfish-1.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1830f125dc2f41babd0101b2d67a325972f79e991af1e0a135d9efe2c890bbbc"}, + {file = "jellyfish-1.0.4-cp310-none-win32.whl", hash = "sha256:169634dc62f7bb9b93c03d3d7b5da327426023d47d58bd8b424c61aaaa33085c"}, + {file = "jellyfish-1.0.4-cp310-none-win_amd64.whl", hash = "sha256:5b87fca57f6240fe4658810587a0ff49f261a6a49943ad003bbc109c358cec2e"}, + {file = "jellyfish-1.0.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:1561cd0d1687113a5b1e4c4f0e1ab373fbc851af0c9c769a486f94f9ede27cd5"}, + {file = "jellyfish-1.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d60ab87c542659bd71ed952fbc9c4186293e49016dd92ca79156fee6574a17d"}, + {file = "jellyfish-1.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ceba547f96de1f58d29f87c816aab4ec02cbeb6606a48fcad1dcf35c1f06042"}, + {file = "jellyfish-1.0.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b1457d3de969f652d6396cb0329cae3f8d75e0851b335f106624bc991c63c80b"}, + {file = "jellyfish-1.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90384f8b4446a84682bb18051cdc17a069963fff1d0af03ccd2b044b62af6d44"}, + {file = "jellyfish-1.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:896552560dcba125db074b980ccc17e123e9444593b272edb82254e4b30f0bd1"}, + {file = "jellyfish-1.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:47b0914f375be24976f26ff1436f22dc9fa1ecf9513dbe7ebbee6af5f85409a2"}, + {file = "jellyfish-1.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1529a9f1627acffda79ab490ca3f67d35ee1e15c2d30b3f9f93be895b212c4c5"}, + {file = "jellyfish-1.0.4-cp311-none-win32.whl", hash = "sha256:4a47daa243798db689f8b1f3e6c811032075fd434e2af9dfea35a1553152e34e"}, + {file = "jellyfish-1.0.4-cp311-none-win_amd64.whl", hash = "sha256:1d42fdf67a34a346d906b0ab8d56db9cc68bf6497382650d4581ec0fc8eef342"}, + {file = "jellyfish-1.0.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:81f68a8ba074ef3630fab6e635d542708c6e7b5c504a546257b796835b28a5d5"}, + {file = "jellyfish-1.0.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:535a7e99c2b6d456b06d160c950379f18cb72effeb856069eae5d024e09b4afd"}, + {file = "jellyfish-1.0.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76b7936b69687d788aabb86875c0780d6a77dbac9d1738503b0091af744ff79b"}, + {file = "jellyfish-1.0.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:015997043c3eecbf686a71838028180d885f0dc4f7e99daf7194e1787ecd5909"}, + {file = "jellyfish-1.0.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66c7c6113565bcd3771882ff1c6a31573ef3ce755f882e1bf27b233c44a24f35"}, + {file = "jellyfish-1.0.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:069d406850c68a43513a4ddbbf4191e83a2b8fb08119d708086a21c2cf6c406e"}, + {file = "jellyfish-1.0.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:642dde8453ae45235c377ad3ce6cc990bf90fe9c4222896ab3f0f6c5609089a4"}, + {file = "jellyfish-1.0.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:967723d8a1321327b3d6e9eada2db95659ff27ab6de8bb8dc82eefe1ce993333"}, + {file = "jellyfish-1.0.4-cp312-none-win32.whl", hash = "sha256:bd33becfa61956c8ebd12bcb7227d48156d7e4c289780bcccf06e55acde12bf6"}, + {file = "jellyfish-1.0.4-cp312-none-win_amd64.whl", hash = "sha256:c3addb4eebadd7cd4f6cdbff55a4a28caf2448333131b20661d4ff342f53e8a4"}, + {file = "jellyfish-1.0.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b365ef28bed2673fffec38775aae36fd9d692ff3e2c6f331ed1898c00cd1f388"}, + {file = "jellyfish-1.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44329a7fa570a167144ef20d8d57dff7c59028ecc392cccd9385d23c321aa784"}, + {file = "jellyfish-1.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59f4d263d15d868372c2dcfe12007707d3448a9253a1d912230f213b456ca697"}, + {file = "jellyfish-1.0.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5dca33ca59163445c8afdedff7f47d7f27f0a88fabedfde4ea7197698adc6335"}, + {file = "jellyfish-1.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42056f50f5c604132ca50088253122c8a0bdbf8f37959b60f4fd75026396be3c"}, + {file = "jellyfish-1.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2c001b7cfb14216108dcc851ac39fb428ed82138dabcd6a20e051a2ec5cd6f9e"}, + {file = "jellyfish-1.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c9c713fb0012db4468c2aff8e3a6b6dbd63908563bec0f0ed508d280f0fc4937"}, + {file = "jellyfish-1.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d78874364780b2a6ec248c3d92fb5343cdc5dadaa552cc564eebe7941678303c"}, + {file = "jellyfish-1.0.4-cp38-none-win32.whl", hash = "sha256:363562fa5d99bc688a187ede4c05a9e220baf296a450fe1a24e2c02a65d0077c"}, + {file = "jellyfish-1.0.4-cp38-none-win_amd64.whl", hash = "sha256:27f51df4818fc3eea3ed32c9f50883c011c9e1f972cc2b04cef614d24179f427"}, + {file = "jellyfish-1.0.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:651f8c75bf4352427f1160c2b1d9e994862cc86a9ce2106e9c0c2d87e973ca88"}, + {file = "jellyfish-1.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a9fd3409238012c3d153b5d3ec5f3fe32648ceb6a86f67d42434f0f5f2447a28"}, + {file = "jellyfish-1.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e003e5db6607b46d7f1e321628a0a04e8f56adcbdd8aadfb6b61ec6764bc028a"}, + {file = "jellyfish-1.0.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2d443734829b7e38a4e4525cc572e6ff6e0588254ae346a11c976b935efdbc54"}, + {file = "jellyfish-1.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:984e6307ed255224dc38370b953b48e6f13950209d76489ade582dedc66a001a"}, + {file = "jellyfish-1.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00e23fb1e87c8b99008fe0a9c00f509754cf0e1a74d9a975fc3737790e756679"}, + {file = "jellyfish-1.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f6f5aaa4f4326feb6754878f3875ee39c5df2e650abe04f9da28c80c3e341728"}, + {file = "jellyfish-1.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d40c3ebd4a00a55845b5653e4a5a8784a032a68e91ca3713163e446b48168887"}, + {file = "jellyfish-1.0.4-cp39-none-win32.whl", hash = "sha256:ce7a7c6ab717d7b8961d234a60c0e12f80a24b4b0ec213a2272f4cdba013b5f8"}, + {file = "jellyfish-1.0.4-cp39-none-win_amd64.whl", hash = "sha256:73e0789d20eda3923a6531693aca1ca6231bec12b9b7c6d7c2ed37b1889f40c1"}, + {file = "jellyfish-1.0.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89f6db50049492c49b622e8e8c04c5494d4c96c92f0ae573288eefb809d60d1f"}, + {file = "jellyfish-1.0.4-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f5af807b15db3c7d08c30911fbe82266ff1089f28ba5a682e87e3145943936cd"}, + {file = "jellyfish-1.0.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17c7822dcb9e70b682604941852f6bba78b047b60d41d2df0e6a75a5d2b1bb78"}, + {file = "jellyfish-1.0.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f581b0184ce7a000f38941b2c81a4480b5fd52cdeb5672f9f682d9e3adb8db84"}, + {file = "jellyfish-1.0.4-pp310-pypy310_pp73-musllinux_1_1_i686.whl", hash = "sha256:f5bc5e05616155306756abe2afda23caefb766b59c849d88285f67bcdcf5a5bb"}, + {file = "jellyfish-1.0.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:4de7c4e7245a2fa9d24bb75dd66aaf77b3521b2377883af0b6008740024ce598"}, + {file = "jellyfish-1.0.4-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e94d594b4b4902a5278346852227f9be281a4aa61907ecd00091451bce8279be"}, + {file = "jellyfish-1.0.4-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:91dc251d02dee6686a1dc31a30a0ea7d8f49781556272b1044cb1a942db75a40"}, + {file = "jellyfish-1.0.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:359aa8c0a55560bd0e6d17e2098b96428d91f066120a708ad889a729801a78b9"}, + {file = "jellyfish-1.0.4-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:02525584cb1d09f3b5b784685a63ba6e889bce240acef12161d7a6f428ea6c2e"}, + {file = "jellyfish-1.0.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9f9d82531af35123632bd02a4394c8783a6f81d89b5c1711bd4c1a6c800a8dc"}, + {file = "jellyfish-1.0.4-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c54255f79a5d00a8261c48e75b483bf1ba2aa87655bd69d4cff805eab758c0f4"}, + {file = "jellyfish-1.0.4-pp38-pypy38_pp73-musllinux_1_1_i686.whl", hash = "sha256:209ccfbc135d150f6af2db9d3c13764f690aa6196fb74ecffd5394c367ed4938"}, + {file = "jellyfish-1.0.4-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3ee641c1c68e0458cac4b9c8c4432d535de1bdd66e8514e541939094622b55cc"}, + {file = "jellyfish-1.0.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d9552ac0478d3015f93161e7d7e1a388b3204fac2a1a22aaf30d67c3670eb6f2"}, + {file = "jellyfish-1.0.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:2cc0a11166cb1cea0700585de63fa46252a5efa46bc31bc4d869b71e3c666ded"}, + {file = "jellyfish-1.0.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6285981622d31c11994f2abcd0d35ec7661cba842538e59bfb735fbedf7b6531"}, + {file = "jellyfish-1.0.4-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07e10f5ab014a626048ff7cd78a6a52c81845f89d94902371278c4be66d91909"}, + {file = "jellyfish-1.0.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8eaa4f2cf78f34cfd41270968954b3bc1eed433b6e7d124786b8064021c110a5"}, + {file = "jellyfish-1.0.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:83e3c4b446da02926b382f8eb8b931e266927e82162adf4c57f0c55c2bf95b35"}, + {file = "jellyfish-1.0.4-pp39-pypy39_pp73-musllinux_1_1_i686.whl", hash = "sha256:d88f47c5c3d97f40b4aa42b83d7ca03707bd6bebd945c9532da6e25515bbeea4"}, + {file = "jellyfish-1.0.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:a4b717a510e64773c4f882b373d4aeda7d2b2b8ffae87c16a906426b7cd02d55"}, + {file = "jellyfish-1.0.4.tar.gz", hash = "sha256:72aabb3bedd513cdd20712242fd51173b59972c0b146b7a0b9c6f32f1656293f"}, +] + [[package]] name = "jinja2" version = "3.1.4" @@ -2514,72 +2633,72 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "jiter" -version = "0.4.1" +version = "0.4.2" description = "Fast iterable JSON parser." optional = false python-versions = ">=3.8" files = [ - {file = "jiter-0.4.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3c2370cd8826b484f3fc6ed729cb58510ba24b4bc277c92323a57d35cf4df223"}, - {file = "jiter-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3587af23140a2eb282bba980010dae60f3b8b1579a034c5e869e9b94220a5972"}, - {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df8788d34545d47de864032a78bae49a14b66b67196c73cd95f1c1e3081d9c73"}, - {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91bf2d31e906a3ca26fc8ee0cb979e0e51b12aa7e83999c6afea047538f95e5c"}, - {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8586e68702666b6acd919c65f718a09603adcfd8b4c7026bade2441d9e7bd34e"}, - {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:639b766bde088546b5205fd31608502b5b42abee3294b43cc95c6ea8f9a257c3"}, - {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cb32457296351c98da289d21a092a6c53c75beb80e7127c8e16224ee342c7c7"}, - {file = "jiter-0.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:583263bd81bce5426806cf27ba85e4b97746797fae13c71e50a8689e06e57f81"}, - {file = "jiter-0.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c0e413999a819ccef9b5fd22ef4b9b8c48a98e49da4d09b43ebce286d0d80e26"}, - {file = "jiter-0.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5e50468d5acfef335ba8bc3892bb304354c38ba18acb3f7ae428451e47136e49"}, - {file = "jiter-0.4.1-cp310-none-win32.whl", hash = "sha256:b2ac90b94dd717644c61c8ed0c2ec6e9505bd7314b91a1549680d7f1cb8f1da4"}, - {file = "jiter-0.4.1-cp310-none-win_amd64.whl", hash = "sha256:2509868b8dacf4f65d04b4d951d390f30f403a87a997a14e2db2d232c7a468a7"}, - {file = "jiter-0.4.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b56e4f2fa5767976f2332e9e067010ddfe1379b6456b5458123ba50657c33e02"}, - {file = "jiter-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f813b49db21c946aa010accc54b8e5c9d0007be252bda4738159fa6c65d6d396"}, - {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2933c04ebd77b3e9cf34f80ba45c093739c687c9c5a4fd0a8c701a3bfd90940"}, - {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b02ddd65513705ec38211ea48ffc0fde41aa46166d9f7706972daf97b57c8599"}, - {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:88d06af883524e5429d75395bb4ee6ddeda4c30818b2f3e3b8f4afa2dd8f28c0"}, - {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd333eca1090cf21e6359721eecbb2a7fe031cc4db3dd595081430b4a59371c5"}, - {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdc90017cd22dca6b40f2f8518b38363e78aee3cb32f84e1cb08900a598ca91b"}, - {file = "jiter-0.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aedce5b11ca58853d46461e1880079836bfab4e132be2b7d2093ec193081bbc8"}, - {file = "jiter-0.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e55b2f4d2d5066979b0e0e58d85e3fffd0f6e6a0523aab7e0ce75950259387da"}, - {file = "jiter-0.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b3c85c586f1cd71c2a1e78756f6857119947b532379bd9be4338bf3dacf1e87f"}, - {file = "jiter-0.4.1-cp311-none-win32.whl", hash = "sha256:37875f56222f2bb61410e15196d9b91510ccca322c391f3d20c91d667130d15e"}, - {file = "jiter-0.4.1-cp311-none-win_amd64.whl", hash = "sha256:b71758befea8dbdc10e0fb40a776e085eed0e74afef42468ebb58562289e9190"}, - {file = "jiter-0.4.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:93a8869c18a3721e41d7adb289c5c71aea8887eb368a3411219a0afb62955cbe"}, - {file = "jiter-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0ffbc61349f2f27676d40d68e8ef83fc2a9dd2c1464962b1d1b1d8504bccbf85"}, - {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5f1f33e9fd4de4369a8d00fdf2571a8246a942095fb2a9d4cd25135ee675c85"}, - {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d8f91a19eba23b4a1bb1e5b64c19cfdbf46604180e5dee40548b53ca13afd2d9"}, - {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a60f8e495448d8e02d291fa9a8522cfe775a10210ba428994f383965e6f6e65"}, - {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7387998c6585ce0f02ae4f5338fabf72b99494860c347f27bc34720290eafb15"}, - {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7cbf41da6506b42db21a1a0befa48e16384591e84e80db002a826ccf07668f1"}, - {file = "jiter-0.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:793ae2499722b9fc31e300abd07418902512109bca17f617598a31a9e17bddce"}, - {file = "jiter-0.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:19f7953b8ada7ee109764ad91d4afb1a9f69b77cde0b890844744c513612dbf8"}, - {file = "jiter-0.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:dcd3d6a142d7b267a8c5f1e28d02759e2e29343b095f6d8aaf463333a842e1f8"}, - {file = "jiter-0.4.1-cp312-none-win32.whl", hash = "sha256:fffdf137c3ab7f0c5facb7c478b57ad3e1eb9b149daff48687844de77b78ab70"}, - {file = "jiter-0.4.1-cp312-none-win_amd64.whl", hash = "sha256:fde004e47a801512c4167f188a6372960374fbd59e635753b3ee536e81953eb3"}, - {file = "jiter-0.4.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b429ba25e05ca28d5e7efa4249032746ac28ec6ad68017ed3ea009989c597911"}, - {file = "jiter-0.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:27df9925d0282c80bdd41613ace7cd799bd6355acdfe25cc48ec16843541999e"}, - {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb68736a0e2b00eda83937c1937f999e8d7dab68820c04343ac2e2eb2c5c2193"}, - {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c218458ac32ce0b495f013293867649b40c067a4d7533fa0d70a46f7194febae"}, - {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ebead86e80e352753f6e6f78ca96c12d764a8dbbc7c4b25938ce657ab0e4e879"}, - {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf58f878d43294bea400a9df86ef7796dd2e67969109bce22d337ca77372c69"}, - {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba671e60570cd99b8ed83ce0d82703040dc34c793229ac607f09683ba1981163"}, - {file = "jiter-0.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef0bd8b68ad14f045544989b6ad3758bee6dc01f6924bce5b4fd7060b0a09b1b"}, - {file = "jiter-0.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7888f165a0fe285e015ee18cfcb8b5432c4fa389235b4c24c339ca0cc51ba979"}, - {file = "jiter-0.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7d9c443b2a71a8c3ab6578f5faf7725ad5f63dbb92d87f820eec56de9da0560f"}, - {file = "jiter-0.4.1-cp38-none-win32.whl", hash = "sha256:6f618d1b04493bc9196e466ef59e0a6388eb85e936d1a61833449677643bbdd9"}, - {file = "jiter-0.4.1-cp38-none-win_amd64.whl", hash = "sha256:46b6364a0b2a81cc259768bda131e8528aa3af4312f23f7e10aa04d24f54bbb1"}, - {file = "jiter-0.4.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:6680785a9273a87e463c86a962042d620c00c7bb8100dde1a4c78b2184cdd613"}, - {file = "jiter-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:36b10d945b9ccd2e9f2720e37395daf9e63cfa47e5e0e2887c4931888f0800cd"}, - {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78820599693bda34be17119abf9fad1f02e501b4816e47addbee9c5c768fb361"}, - {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68697317170d8f851dfe978ba278b886e54e837ecd2a80c4a33ae780a0f19526"}, - {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d126ffc3876cfc1fba6ae2be37f2532b5db593a96cf4b845724b50b44339c4fd"}, - {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b082223f2e7e6f506d837df935f58f25cabf0a2b35902b4ec73fb561fbf2694a"}, - {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13314287782782be8439dfafca50f13fcab18046227068a3a8e8d8ac888f092b"}, - {file = "jiter-0.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3da1346375605926f1ca4604d154ff41f5e3b933c6e01005e534bca2197d919f"}, - {file = "jiter-0.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9b67a97fbce3ec35ee97439c8b786393f71ecbe7458d5e9279d4c172772eac36"}, - {file = "jiter-0.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7b0f34544923bff0f3393aa3d60087686d86089c9361f6530bb5d19ebfb3db47"}, - {file = "jiter-0.4.1-cp39-none-win32.whl", hash = "sha256:b0c93ef95b896a4ce5edff23071e4dcad77c9e9262fcb6ca2b050f781e8335a9"}, - {file = "jiter-0.4.1-cp39-none-win_amd64.whl", hash = "sha256:3db5c83c8655ce031943b6f08434dac1a91e1477b0df452de0c44f3390a9b22c"}, - {file = "jiter-0.4.1.tar.gz", hash = "sha256:741851cf5f37cf3583f2a56829d734c9fd17334770c9a326e6d25291603d4278"}, + {file = "jiter-0.4.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c2b003ff58d14f5e182b875acd5177b2367245c19a03be9a2230535d296f7550"}, + {file = "jiter-0.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b48c77c25f094707731cd5bad6b776046846b60a27ee20efc8fadfb10a89415f"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f50ad6b172bde4d45f4d4ea10c49282a337b8bb735afc99763dfa55ea84a743"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95f6001e86f525fbbc9706db2078dc22be078b0950de55b92d37041930f5f940"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16646ef23b62b007de80460d303ebb2d81e355dac9389c787cec87cdd7ffef2f"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b4e847c13b0bf1255c711a92330e7a8cb8b5cdd1e37d7db309627bcdd3367ff"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c536589be60e4c5f2b20fadc4db7e9f55d4c9df3551f29ddf1c4a18dcc9dd54"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3b2763996167830889a854b4ded30bb90897f9b76be78069c50c3ec4540950e"}, + {file = "jiter-0.4.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:675e8ab98c99495091af6b6e9bf2b6353bcf81f25ab6ce27d36127e315b4505d"}, + {file = "jiter-0.4.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e48e43d9d999aaf55f53406b8846ff8cbe3e47ee4b9dc37e5a10a65ce760809f"}, + {file = "jiter-0.4.2-cp310-none-win32.whl", hash = "sha256:881b6e67c50bc36acb3570eda693763c8cd77d590940e06fa6d325d0da52ec1b"}, + {file = "jiter-0.4.2-cp310-none-win_amd64.whl", hash = "sha256:bb8f7b43259efc6add0d721ade2953e064b24e2026d26d979bc09ec080844cef"}, + {file = "jiter-0.4.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:24ad336ac47f274fa83f6fbedcabff9d3387c80f67c66b992688e6a8ba2c47e9"}, + {file = "jiter-0.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fc392a220095730afe365ce1516f2f88bb085a2fd29ea191be9c6e3c71713d9a"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1fdc408de36c81460896de0176f2f7b9f3574dcd35693a0b2c00f4ca34c98e4"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c10ad76722ee6a8c820b0db06a793c08b7d679e5201b9563015bd1e06c959a09"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dbb46d1e9c82bba87f0cbda38413e49448a7df35b1e55917124bff9f38974a23"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:194e28ef4b5f3b61408cb2ee6b6dcbcdb0c9063d01b92b01345b7605692849f5"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f0a447533eccd62748a727e058efa10a8d7cf1de8ffe1a4d705ecb41dad9090"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5f7704d7260bbb88cca3453951af739589132b26e896a3144fa2dae2263716d7"}, + {file = "jiter-0.4.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:01427458bc9550f2eda09d425755330e7d0eb09adce099577433bebf05d28d59"}, + {file = "jiter-0.4.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:159b8416879c0053b17c352f70b67b749ef5b2924c6154318ecf71918aab0905"}, + {file = "jiter-0.4.2-cp311-none-win32.whl", hash = "sha256:f2445234acfb79048ce1a0d5d0e181abb9afd9e4a29d8d9988fe26cc5773a81a"}, + {file = "jiter-0.4.2-cp311-none-win_amd64.whl", hash = "sha256:e15a65f233b6b0e5ac10ddf3b97ceb18aa9ffba096259961641d78b4ee321bd5"}, + {file = "jiter-0.4.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:d61d59521aea9745447ce50f74d39a16ef74ec9d6477d9350d77e75a3d774ad2"}, + {file = "jiter-0.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eef607dc0acc251923427808dbd017f1998ae3c1a0430a261527aa5cbb3a942"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af6bf39954646e374fc47429c656372ac731a6a26b644158a5a84bcdbed33a47"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f509d23606e476852ee46a2b65b5c4ad3905f17424d9cc19c1dffa1c94ba3c6"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59672774daa44ee140aada0c781c82bee4d9ac5e522966186cfb6b3c217d8a51"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:24a0458efac5afeca254cf557b8a654e17013075a69905c78f88d557f129d871"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8860766d1c293e75c1bb4e25b74fa987e3adf199cac3f5f9e6e49c2bebf092f"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a109f3281b72bbf4921fe43db1005c004a38559ca0b6c4985add81777dfe0a44"}, + {file = "jiter-0.4.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:faa7e667454b77ad2f0ef87db39f4944de759617aadf210ea2b73f26bb24755f"}, + {file = "jiter-0.4.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3512f8b00cafb6780b427cb6282800d2bf8277161d9c917830661bd4ed1d3528"}, + {file = "jiter-0.4.2-cp312-none-win32.whl", hash = "sha256:853b35d508ee5b66d06630473c1c0b7bb5e29bf4785c9d2202437116c94f7e21"}, + {file = "jiter-0.4.2-cp312-none-win_amd64.whl", hash = "sha256:4a3a8197784278eb8b24cb02c45e1cad67c2ce5b5b758adfb19b87f74bbdff9c"}, + {file = "jiter-0.4.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ca2a4d750aed3154b89f2efb148609fc985fad8db739460797aaf9b478acedda"}, + {file = "jiter-0.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0e6c304b3cc6896256727e1fb8991c7179a345eca8224e201795e9cacf4683b0"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cc34ac708ae1750d077e490321761ec4b9a055b994cbdd1d6fbd37099e4aa7b"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8c93383875ab8d2e4f760aaff335b4a12ff32d4f9cf49c4498d657734f611466"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce197ee044add576afca0955b42142dd0312639adb6ebadbdbe4277f2855614f"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a427716813ff65480ca5b5117cfa099f49b49cd38051f8609bd0d5493013ca0"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:479990218353356234669e70fac53e5eb6f739a10db25316171aede2c97d9364"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d35a91ec5ac74cf33234c431505299fa91c0a197c2dbafd47400aca7c69489d4"}, + {file = "jiter-0.4.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b27189847193708c94ad10ca0d891309342ae882725d2187cf5d2db02bde8d1b"}, + {file = "jiter-0.4.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:76c255308cd1093fb411a03756b7bb220e48d4a98c30cbc79ed448bf3978e27d"}, + {file = "jiter-0.4.2-cp38-none-win32.whl", hash = "sha256:bb77438060bad49cc251941e6701b31138365c8a0ddaf10cdded2fcc6dd30701"}, + {file = "jiter-0.4.2-cp38-none-win_amd64.whl", hash = "sha256:ce858af19f7ce0d4b51c9f6c0c9d08f1e9dcef1986c5875efd0674a7054292ca"}, + {file = "jiter-0.4.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:6128838a2f357b3921b2a3242d5dc002ae4255ecc8f9f05c20d56d7d2d79c5ad"}, + {file = "jiter-0.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f2420cebb9ba856cb57dcab1d2d8def949b464b0db09c22a4e4dbd52fff7b200"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5d13d8128e853b320e00bb18bd4bb8b136cc0936091dc87633648fc688eb705"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eba5d6e54f149c508ba88677f97d3dc7dd75e9980d234bbac8027ac6db0763a3"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0fad5d64af0bc0545237419bf4150d8de56f0bd217434bdd1a59730327252bef"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d179e7bca89cf5719bd761dd37a341ff0f98199ecaa9c14af09792e47e977cc"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36353caee9f103d8ee7bda077f6400505b0f370e27eabcab33a33d21de12a2a6"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dd146c25bce576ca5db64fc7eccb8862af00f1f0e30108796953f12a53660e4c"}, + {file = "jiter-0.4.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:14b7c08cadbcd703041c66dc30e24e17de2f340281cac0e69374223ecf153aa4"}, + {file = "jiter-0.4.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a90f1a8b3d29aea198f8ea2b01148276ced8056e5103f32525266b3d880e65c9"}, + {file = "jiter-0.4.2-cp39-none-win32.whl", hash = "sha256:25b174997c780337b61ae57b1723455eecae9a17a9659044fd3c3b369190063f"}, + {file = "jiter-0.4.2-cp39-none-win_amd64.whl", hash = "sha256:bef62cea18521c5b99368147040c7e560c55098a35c93456f110678a2d34189a"}, + {file = "jiter-0.4.2.tar.gz", hash = "sha256:29b9d44f23f0c05f46d482f4ebf03213ee290d77999525d0975a17f875bf1eea"}, ] [[package]] @@ -2595,13 +2714,13 @@ files = [ [[package]] name = "joblib" -version = "1.3.2" +version = "1.4.2" description = "Lightweight pipelining with Python functions" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "joblib-1.3.2-py3-none-any.whl", hash = "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9"}, - {file = "joblib-1.3.2.tar.gz", hash = "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1"}, + {file = "joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6"}, + {file = "joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"}, ] [[package]] @@ -2655,24 +2774,24 @@ ply = "*" [[package]] name = "jsonpointer" -version = "2.4" +version = "3.0.0" description = "Identify specific nodes in a JSON document (RFC 6901)" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +python-versions = ">=3.7" files = [ - {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, - {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, + {file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"}, + {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, ] [[package]] name = "jsonschema" -version = "4.22.0" +version = "4.23.0" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.8" files = [ - {file = "jsonschema-4.22.0-py3-none-any.whl", hash = "sha256:ff4cfd6b1367a40e7bc6411caec72effadd3db0bbe5017de188f2d6108335802"}, - {file = "jsonschema-4.22.0.tar.gz", hash = "sha256:5b22d434a45935119af990552c862e5d6d564e8f6601206b305a61fdf661a2b7"}, + {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, + {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, ] [package.dependencies] @@ -2687,11 +2806,11 @@ rfc3339-validator = {version = "*", optional = true, markers = "extra == \"forma rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} rpds-py = ">=0.7.1" uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -webcolors = {version = ">=1.11", optional = true, markers = "extra == \"format-nongpl\""} +webcolors = {version = ">=24.6.0", optional = true, markers = "extra == \"format-nongpl\""} [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"] [[package]] name = "jsonschema-specifications" @@ -2792,13 +2911,13 @@ jupyter-server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.14.1" +version = "2.14.2" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server-2.14.1-py3-none-any.whl", hash = "sha256:16f7177c3a4ea8fe37784e2d31271981a812f0b2874af17339031dc3510cc2a5"}, - {file = "jupyter_server-2.14.1.tar.gz", hash = "sha256:12558d158ec7a0653bf96cc272bc7ad79e0127d503b982ed144399346694f726"}, + {file = "jupyter_server-2.14.2-py3-none-any.whl", hash = "sha256:47ff506127c2f7851a17bf4713434208fc490955d0e8632e95014a9a9afbeefd"}, + {file = "jupyter_server-2.14.2.tar.gz", hash = "sha256:66095021aa9638ced276c248b1d81862e4c50f292d575920bbe960de1c56b12b"}, ] [package.dependencies] @@ -2847,13 +2966,13 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.2.1" +version = "4.2.4" description = "JupyterLab computational environment" optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab-4.2.1-py3-none-any.whl", hash = "sha256:6ac6e3827b3c890e6e549800e8a4f4aaea6a69321e2240007902aa7a0c56a8e4"}, - {file = "jupyterlab-4.2.1.tar.gz", hash = "sha256:a10fb71085a6900820c62d43324005046402ffc8f0fde696103e37238a839507"}, + {file = "jupyterlab-4.2.4-py3-none-any.whl", hash = "sha256:807a7ec73637744f879e112060d4b9d9ebe028033b7a429b2d1f4fc523d00245"}, + {file = "jupyterlab-4.2.4.tar.gz", hash = "sha256:343a979fb9582fd08c8511823e320703281cd072a0049bcdafdc7afeda7f2537"}, ] [package.dependencies] @@ -2868,6 +2987,7 @@ jupyter-server = ">=2.4.0,<3" jupyterlab-server = ">=2.27.1,<3" notebook-shim = ">=0.2" packaging = "*" +setuptools = ">=40.1.0" tomli = {version = ">=1.2.2", markers = "python_version < \"3.11\""} tornado = ">=6.2.0" traitlets = "*" @@ -2877,7 +2997,7 @@ dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-jupyter", "sphinx (>=1.8,<7.3.0)", "sphinx-copybutton"] docs-screenshots = ["altair (==5.3.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.2)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.1.post2)", "matplotlib (==3.8.3)", "nbconvert (>=7.0.0)", "pandas (==2.2.1)", "scipy (==1.12.0)", "vega-datasets (==0.9.0)"] test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] -upgrade-extension = ["copier (>=8,<10)", "jinja2-time (<0.3)", "pydantic (<2.0)", "pyyaml-include (<2.0)", "tomli-w (<2.0)"] +upgrade-extension = ["copier (>=9,<10)", "jinja2-time (<0.3)", "pydantic (<3.0)", "pyyaml-include (<3.0)", "tomli-w (<2.0)"] [[package]] name = "jupyterlab-pygments" @@ -2892,13 +3012,13 @@ files = [ [[package]] name = "jupyterlab-server" -version = "2.27.2" +version = "2.27.3" description = "A set of server components for JupyterLab and JupyterLab like applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab_server-2.27.2-py3-none-any.whl", hash = "sha256:54aa2d64fd86383b5438d9f0c032f043c4d8c0264b8af9f60bd061157466ea43"}, - {file = "jupyterlab_server-2.27.2.tar.gz", hash = "sha256:15cbb349dc45e954e09bacf81b9f9bcb10815ff660fb2034ecd7417db3a7ea27"}, + {file = "jupyterlab_server-2.27.3-py3-none-any.whl", hash = "sha256:e697488f66c3db49df675158a77b3b017520d772c6e1548c7d9bcc5df7944ee4"}, + {file = "jupyterlab_server-2.27.3.tar.gz", hash = "sha256:eb36caca59e74471988f0ae25c77945610b887f777255aa21f8065def9e51ed4"}, ] [package.dependencies] @@ -2918,13 +3038,13 @@ test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-v [[package]] name = "jupytext" -version = "1.16.2" +version = "1.16.3" description = "Jupyter notebooks as Markdown documents, Julia, Python or R scripts" optional = false python-versions = ">=3.8" files = [ - {file = "jupytext-1.16.2-py3-none-any.whl", hash = "sha256:197a43fef31dca612b68b311e01b8abd54441c7e637810b16b6cb8f2ab66065e"}, - {file = "jupytext-1.16.2.tar.gz", hash = "sha256:8627dd9becbbebd79cc4a4ed4727d89d78e606b4b464eab72357b3b029023a14"}, + {file = "jupytext-1.16.3-py3-none-any.whl", hash = "sha256:870e0d7a716dcb1303df6ad1cec65e3315a20daedd808a55cb3dae2d56e4ed20"}, + {file = "jupytext-1.16.3.tar.gz", hash = "sha256:1ebac990461dd9f477ff7feec9e3003fa1acc89f3c16ba01b73f79fd76f01a98"}, ] [package.dependencies] @@ -2936,15 +3056,41 @@ pyyaml = "*" tomli = {version = "*", markers = "python_version < \"3.11\""} [package.extras] -dev = ["autopep8", "black", "flake8", "gitpython", "ipykernel", "isort", "jupyter-fs (<0.4.0)", "jupyter-server (!=2.11)", "nbconvert", "pre-commit", "pytest", "pytest-cov (>=2.6.1)", "pytest-randomly", "pytest-xdist", "sphinx-gallery (<0.8)"] +dev = ["autopep8", "black", "flake8", "gitpython", "ipykernel", "isort", "jupyter-fs (>=1.0)", "jupyter-server (!=2.11)", "nbconvert", "pre-commit", "pytest", "pytest-cov (>=2.6.1)", "pytest-randomly", "pytest-xdist", "sphinx-gallery (<0.8)"] docs = ["myst-parser", "sphinx", "sphinx-copybutton", "sphinx-rtd-theme"] test = ["pytest", "pytest-randomly", "pytest-xdist"] test-cov = ["ipykernel", "jupyter-server (!=2.11)", "nbconvert", "pytest", "pytest-cov (>=2.6.1)", "pytest-randomly", "pytest-xdist"] -test-external = ["autopep8", "black", "flake8", "gitpython", "ipykernel", "isort", "jupyter-fs (<0.4.0)", "jupyter-server (!=2.11)", "nbconvert", "pre-commit", "pytest", "pytest-randomly", "pytest-xdist", "sphinx-gallery (<0.8)"] +test-external = ["autopep8", "black", "flake8", "gitpython", "ipykernel", "isort", "jupyter-fs (>=1.0)", "jupyter-server (!=2.11)", "nbconvert", "pre-commit", "pytest", "pytest-randomly", "pytest-xdist", "sphinx-gallery (<0.8)"] test-functional = ["pytest", "pytest-randomly", "pytest-xdist"] test-integration = ["ipykernel", "jupyter-server (!=2.11)", "nbconvert", "pytest", "pytest-randomly", "pytest-xdist"] test-ui = ["calysto-bash"] +[[package]] +name = "keybert" +version = "0.8.5" +description = "KeyBERT performs keyword extraction with state-of-the-art transformer models." +optional = false +python-versions = ">=3.8" +files = [ + {file = "keybert-0.8.5-py3-none-any.whl", hash = "sha256:005e0eab30c8e85c249ccc6eaad7741357e692591b3eaebe64c40f12614c2ca9"}, + {file = "keybert-0.8.5.tar.gz", hash = "sha256:4b8e4b4d129b319b6266c77b9c8ed34e94e5db42a977c977c8ae58f57343995f"}, +] + +[package.dependencies] +numpy = ">=1.18.5" +rich = ">=10.4.0" +scikit-learn = ">=0.22.2" +sentence-transformers = ">=0.3.8" + +[package.extras] +dev = ["keybert[docs,test]"] +docs = ["mkdocs (>=1.1)", "mkdocs-material (>=4.6.3)", "mkdocstrings (>=0.8.0)"] +flair = ["flair (>=0.7)", "torch (>=1.4.0)", "transformers (>=3.5.1)"] +gensim = ["gensim (>=3.6.0)"] +spacy = ["spacy (>=3.0.1)"] +test = ["black (>=19.3b0)", "flake8 (>=3.6.0)", "pre-commit (>=2.2.0)", "pytest (>=5.4.3)", "pytest-cov (>=2.6.1)"] +use = ["tensorflow", "tensorflow-hub", "tensorflow-text"] + [[package]] name = "kiwisolver" version = "1.4.5" @@ -3096,42 +3242,36 @@ tests = ["aiohttp", "boto3", "duckdb", "pandas (>=1.4)", "polars (>=0.19)", "pyt [[package]] name = "langchain-core" -version = "0.2.2" +version = "0.2.19" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_core-0.2.2-py3-none-any.whl", hash = "sha256:4b3b55a5f214acbcf8d6d8e322da3a9d6248d6b6f45ac1b86ab0494fd3716128"}, - {file = "langchain_core-0.2.2.tar.gz", hash = "sha256:6884a87f7ac8e0d43e4d83c5f9efa95236c7bd535e22a0a51db19156875b4cd6"}, + {file = "langchain_core-0.2.19-py3-none-any.whl", hash = "sha256:5b3cd34395be274c89e822c84f0e03c4da14168c177a83921c5b9414ac7a0651"}, + {file = "langchain_core-0.2.19.tar.gz", hash = "sha256:13043a83e5c9ab58b9f5ce2a56896e7e88b752e8891b2958960a98e71801471e"}, ] [package.dependencies] jsonpatch = ">=1.33,<2.0" -langsmith = ">=0.1.0,<0.2.0" -packaging = ">=23.2,<24.0" -pydantic = ">=1,<3" +langsmith = ">=0.1.75,<0.2.0" +packaging = ">=23.2,<25" +pydantic = {version = ">=1,<3", markers = "python_full_version < \"3.12.4\""} PyYAML = ">=5.3" -tenacity = ">=8.1.0,<9.0.0" - -[package.extras] -extended-testing = ["jinja2 (>=3,<4)"] +tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<9.0.0" [[package]] name = "langchain-text-splitters" -version = "0.2.1" +version = "0.2.2" description = "LangChain text splitting utilities" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_text_splitters-0.2.1-py3-none-any.whl", hash = "sha256:c2774a85f17189eaca50339629d2316d13130d4a8d9f1a1a96f3a03670c4a138"}, - {file = "langchain_text_splitters-0.2.1.tar.gz", hash = "sha256:06853d17d7241ecf5c97c7b6ef01f600f9b0fb953dd997838142a527a4f32ea4"}, + {file = "langchain_text_splitters-0.2.2-py3-none-any.whl", hash = "sha256:1c80d4b11b55e2995f02d2a326c0323ee1eeff24507329bb22924e420c782dff"}, + {file = "langchain_text_splitters-0.2.2.tar.gz", hash = "sha256:a1e45de10919fa6fb080ef0525deab56557e9552083600455cb9fa4238076140"}, ] [package.dependencies] -langchain-core = ">=0.2.0,<0.3.0" - -[package.extras] -extended-testing = ["beautifulsoup4 (>=4.12.3,<5.0.0)", "lxml (>=4.9.3,<6.0)"] +langchain-core = ">=0.2.10,<0.3.0" [[package]] name = "langcodes" @@ -3153,16 +3293,17 @@ test = ["pytest", "pytest-cov"] [[package]] name = "langfuse" -version = "2.35.2" +version = "2.39.2" description = "A client library for accessing langfuse" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langfuse-2.35.2-py3-none-any.whl", hash = "sha256:d01a23842cab484594f03878aacb9732ef8fd361158eb819c7bf43f758a0954b"}, - {file = "langfuse-2.35.2.tar.gz", hash = "sha256:32b2e6c5bc71b4efdc430c6b964ab1c1e1ba1e105a4a73912c38b3959dc4502d"}, + {file = "langfuse-2.39.2-py3-none-any.whl", hash = "sha256:ef2016704c0366026b93c6613e5ea8e0a2a0bfdbee1a887aa43fb08c6a255e10"}, + {file = "langfuse-2.39.2.tar.gz", hash = "sha256:bb1264722d4968309f3608af01186e0395bcd398a30792579a5f51d5fe1f4902"}, ] [package.dependencies] +anyio = ">=4.4.0,<5.0.0" backoff = ">=1.10.0" httpx = ">=0.15.4,<1.0" idna = ">=3.7,<4.0" @@ -3177,17 +3318,18 @@ openai = ["openai (>=0.27.8)"] [[package]] name = "langsmith" -version = "0.1.5" +version = "0.1.93" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false -python-versions = ">=3.8.1,<4.0" +python-versions = "<4.0,>=3.8.1" files = [ - {file = "langsmith-0.1.5-py3-none-any.whl", hash = "sha256:a1811821a923d90e53bcbacdd0988c3c366aff8f4c120d8777e7af8ecda06268"}, - {file = "langsmith-0.1.5.tar.gz", hash = "sha256:aa7a2861aa3d9ae563a077c622953533800466c4e2e539b0d567b84d5fd5b157"}, + {file = "langsmith-0.1.93-py3-none-any.whl", hash = "sha256:811210b9d5f108f36431bd7b997eb9476a9ecf5a2abd7ddbb606c1cdcf0f43ce"}, + {file = "langsmith-0.1.93.tar.gz", hash = "sha256:285b6ad3a54f50fa8eb97b5f600acc57d0e37e139dd8cf2111a117d0435ba9b4"}, ] [package.dependencies] -pydantic = ">=1,<3" +orjson = ">=3.9.14,<4.0.0" +pydantic = {version = ">=1,<3", markers = "python_full_version < \"3.12.4\""} requests = ">=2,<3" [[package]] @@ -3254,13 +3396,13 @@ dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptio [[package]] name = "makefun" -version = "1.15.2" +version = "1.15.4" description = "Small library to dynamically create python functions." optional = false python-versions = "*" files = [ - {file = "makefun-1.15.2-py2.py3-none-any.whl", hash = "sha256:1c83abfaefb6c3c7c83ed4a993b4a310af80adf6db15625b184b1f0f7545a041"}, - {file = "makefun-1.15.2.tar.gz", hash = "sha256:16f2a2b34d9ee0c2b578c960a1808c974e2822cf79f6e9b9c455aace10882d45"}, + {file = "makefun-1.15.4-py2.py3-none-any.whl", hash = "sha256:945d078a7e01a903f2cbef738b33e0ebc52b8d35fb7e20c528ed87b5c80db5b7"}, + {file = "makefun-1.15.4.tar.gz", hash = "sha256:9f9b9904e7c397759374a88f4c57781fbab2a458dec78df4b3ee6272cd9fb010"}, ] [[package]] @@ -3479,40 +3621,40 @@ files = [ [[package]] name = "matplotlib" -version = "3.9.0" +version = "3.9.1" description = "Python plotting package" optional = false python-versions = ">=3.9" files = [ - {file = "matplotlib-3.9.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2bcee1dffaf60fe7656183ac2190bd630842ff87b3153afb3e384d966b57fe56"}, - {file = "matplotlib-3.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f988bafb0fa39d1074ddd5bacd958c853e11def40800c5824556eb630f94d3b"}, - {file = "matplotlib-3.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe428e191ea016bb278758c8ee82a8129c51d81d8c4bc0846c09e7e8e9057241"}, - {file = "matplotlib-3.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaf3978060a106fab40c328778b148f590e27f6fa3cd15a19d6892575bce387d"}, - {file = "matplotlib-3.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2e7f03e5cbbfacdd48c8ea394d365d91ee8f3cae7e6ec611409927b5ed997ee4"}, - {file = "matplotlib-3.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:13beb4840317d45ffd4183a778685e215939be7b08616f431c7795276e067463"}, - {file = "matplotlib-3.9.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:063af8587fceeac13b0936c42a2b6c732c2ab1c98d38abc3337e430e1ff75e38"}, - {file = "matplotlib-3.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a2fa6d899e17ddca6d6526cf6e7ba677738bf2a6a9590d702c277204a7c6152"}, - {file = "matplotlib-3.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:550cdda3adbd596078cca7d13ed50b77879104e2e46392dcd7c75259d8f00e85"}, - {file = "matplotlib-3.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76cce0f31b351e3551d1f3779420cf8f6ec0d4a8cf9c0237a3b549fd28eb4abb"}, - {file = "matplotlib-3.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c53aeb514ccbbcbab55a27f912d79ea30ab21ee0531ee2c09f13800efb272674"}, - {file = "matplotlib-3.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:a5be985db2596d761cdf0c2eaf52396f26e6a64ab46bd8cd810c48972349d1be"}, - {file = "matplotlib-3.9.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c79f3a585f1368da6049318bdf1f85568d8d04b2e89fc24b7e02cc9b62017382"}, - {file = "matplotlib-3.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bdd1ecbe268eb3e7653e04f451635f0fb0f77f07fd070242b44c076c9106da84"}, - {file = "matplotlib-3.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d38e85a1a6d732f645f1403ce5e6727fd9418cd4574521d5803d3d94911038e5"}, - {file = "matplotlib-3.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a490715b3b9984fa609116481b22178348c1a220a4499cda79132000a79b4db"}, - {file = "matplotlib-3.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8146ce83cbc5dc71c223a74a1996d446cd35cfb6a04b683e1446b7e6c73603b7"}, - {file = "matplotlib-3.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:d91a4ffc587bacf5c4ce4ecfe4bcd23a4b675e76315f2866e588686cc97fccdf"}, - {file = "matplotlib-3.9.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:616fabf4981a3b3c5a15cd95eba359c8489c4e20e03717aea42866d8d0465956"}, - {file = "matplotlib-3.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cd53c79fd02f1c1808d2cfc87dd3cf4dbc63c5244a58ee7944497107469c8d8a"}, - {file = "matplotlib-3.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06a478f0d67636554fa78558cfbcd7b9dba85b51f5c3b5a0c9be49010cf5f321"}, - {file = "matplotlib-3.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81c40af649d19c85f8073e25e5806926986806fa6d54be506fbf02aef47d5a89"}, - {file = "matplotlib-3.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52146fc3bd7813cc784562cb93a15788be0b2875c4655e2cc6ea646bfa30344b"}, - {file = "matplotlib-3.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:0fc51eaa5262553868461c083d9adadb11a6017315f3a757fc45ec6ec5f02888"}, - {file = "matplotlib-3.9.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bd4f2831168afac55b881db82a7730992aa41c4f007f1913465fb182d6fb20c0"}, - {file = "matplotlib-3.9.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:290d304e59be2b33ef5c2d768d0237f5bd132986bdcc66f80bc9bcc300066a03"}, - {file = "matplotlib-3.9.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ff2e239c26be4f24bfa45860c20ffccd118d270c5b5d081fa4ea409b5469fcd"}, - {file = "matplotlib-3.9.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:af4001b7cae70f7eaacfb063db605280058246de590fa7874f00f62259f2df7e"}, - {file = "matplotlib-3.9.0.tar.gz", hash = "sha256:e6d29ea6c19e34b30fb7d88b7081f869a03014f66fe06d62cc77d5a6ea88ed7a"}, + {file = "matplotlib-3.9.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7ccd6270066feb9a9d8e0705aa027f1ff39f354c72a87efe8fa07632f30fc6bb"}, + {file = "matplotlib-3.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:591d3a88903a30a6d23b040c1e44d1afdd0d778758d07110eb7596f811f31842"}, + {file = "matplotlib-3.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd2a59ff4b83d33bca3b5ec58203cc65985367812cb8c257f3e101632be86d92"}, + {file = "matplotlib-3.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fc001516ffcf1a221beb51198b194d9230199d6842c540108e4ce109ac05cc0"}, + {file = "matplotlib-3.9.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:83c6a792f1465d174c86d06f3ae85a8fe36e6f5964633ae8106312ec0921fdf5"}, + {file = "matplotlib-3.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:421851f4f57350bcf0811edd754a708d2275533e84f52f6760b740766c6747a7"}, + {file = "matplotlib-3.9.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b3fce58971b465e01b5c538f9d44915640c20ec5ff31346e963c9e1cd66fa812"}, + {file = "matplotlib-3.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a973c53ad0668c53e0ed76b27d2eeeae8799836fd0d0caaa4ecc66bf4e6676c0"}, + {file = "matplotlib-3.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82cd5acf8f3ef43f7532c2f230249720f5dc5dd40ecafaf1c60ac8200d46d7eb"}, + {file = "matplotlib-3.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab38a4f3772523179b2f772103d8030215b318fef6360cb40558f585bf3d017f"}, + {file = "matplotlib-3.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2315837485ca6188a4b632c5199900e28d33b481eb083663f6a44cfc8987ded3"}, + {file = "matplotlib-3.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:a0c977c5c382f6696caf0bd277ef4f936da7e2aa202ff66cad5f0ac1428ee15b"}, + {file = "matplotlib-3.9.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:565d572efea2b94f264dd86ef27919515aa6d629252a169b42ce5f570db7f37b"}, + {file = "matplotlib-3.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d397fd8ccc64af2ec0af1f0efc3bacd745ebfb9d507f3f552e8adb689ed730a"}, + {file = "matplotlib-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26040c8f5121cd1ad712abffcd4b5222a8aec3a0fe40bc8542c94331deb8780d"}, + {file = "matplotlib-3.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d12cb1837cffaac087ad6b44399d5e22b78c729de3cdae4629e252067b705e2b"}, + {file = "matplotlib-3.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0e835c6988edc3d2d08794f73c323cc62483e13df0194719ecb0723b564e0b5c"}, + {file = "matplotlib-3.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:44a21d922f78ce40435cb35b43dd7d573cf2a30138d5c4b709d19f00e3907fd7"}, + {file = "matplotlib-3.9.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:0c584210c755ae921283d21d01f03a49ef46d1afa184134dd0f95b0202ee6f03"}, + {file = "matplotlib-3.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11fed08f34fa682c2b792942f8902e7aefeed400da71f9e5816bea40a7ce28fe"}, + {file = "matplotlib-3.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0000354e32efcfd86bda75729716b92f5c2edd5b947200be9881f0a671565c33"}, + {file = "matplotlib-3.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4db17fea0ae3aceb8e9ac69c7e3051bae0b3d083bfec932240f9bf5d0197a049"}, + {file = "matplotlib-3.9.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:208cbce658b72bf6a8e675058fbbf59f67814057ae78165d8a2f87c45b48d0ff"}, + {file = "matplotlib-3.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:dc23f48ab630474264276be156d0d7710ac6c5a09648ccdf49fef9200d8cbe80"}, + {file = "matplotlib-3.9.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3fda72d4d472e2ccd1be0e9ccb6bf0d2eaf635e7f8f51d737ed7e465ac020cb3"}, + {file = "matplotlib-3.9.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:84b3ba8429935a444f1fdc80ed930babbe06725bcf09fbeb5c8757a2cd74af04"}, + {file = "matplotlib-3.9.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b918770bf3e07845408716e5bbda17eadfc3fcbd9307dc67f37d6cf834bb3d98"}, + {file = "matplotlib-3.9.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f1f2e5d29e9435c97ad4c36fb6668e89aee13d48c75893e25cef064675038ac9"}, + {file = "matplotlib-3.9.1.tar.gz", hash = "sha256:de06b19b8db95dd33d0dc17c926c7c9ebed9f572074b6fac4f65068a6814d010"}, ] [package.dependencies] @@ -3673,12 +3815,13 @@ pyyaml = ">=5.1" [[package]] name = "mkdocs-jupyter" -version = "0.24.7" +version = "0.24.8" description = "Use Jupyter in mkdocs websites" optional = false python-versions = ">=3.8" files = [ - {file = "mkdocs_jupyter-0.24.7-py3-none-any.whl", hash = "sha256:893d04bea1e007479a46e4e72852cd4d280c4d358ce4a0445250f3f80c639723"}, + {file = "mkdocs_jupyter-0.24.8-py3-none-any.whl", hash = "sha256:36438a0a653eee2c27c6a8f7006e645f18693699c9b8ac44ffde830ddb08fa16"}, + {file = "mkdocs_jupyter-0.24.8.tar.gz", hash = "sha256:09a762f484d540d9c0e944d34b28cb536a32869e224b460e2fc791b143f76940"}, ] [package.dependencies] @@ -3691,13 +3834,13 @@ pygments = ">2.12.0" [[package]] name = "mkdocs-material" -version = "9.5.26" +version = "9.5.29" description = "Documentation that simply works" optional = false python-versions = ">=3.8" files = [ - {file = "mkdocs_material-9.5.26-py3-none-any.whl", hash = "sha256:5d01fb0aa1c7946a1e3ae8689aa2b11a030621ecb54894e35aabb74c21016312"}, - {file = "mkdocs_material-9.5.26.tar.gz", hash = "sha256:56aeb91d94cffa43b6296fa4fbf0eb7c840136e563eecfd12c2d9e92e50ba326"}, + {file = "mkdocs_material-9.5.29-py3-none-any.whl", hash = "sha256:afc1f508e2662ded95f0a35a329e8a5acd73ee88ca07ba73836eb6fcdae5d8b4"}, + {file = "mkdocs_material-9.5.29.tar.gz", hash = "sha256:3e977598ec15a4ddad5c4dfc9e08edab6023edb51e88f0729bd27be77e3d322a"}, ] [package.dependencies] @@ -3807,6 +3950,24 @@ files = [ griffe = ">=0.37" mkdocstrings = ">=0.20" +[[package]] +name = "mkl" +version = "2021.4.0" +description = "Intel® oneAPI Math Kernel Library" +optional = false +python-versions = "*" +files = [ + {file = "mkl-2021.4.0-py2.py3-none-macosx_10_15_x86_64.macosx_11_0_x86_64.whl", hash = "sha256:67460f5cd7e30e405b54d70d1ed3ca78118370b65f7327d495e9c8847705e2fb"}, + {file = "mkl-2021.4.0-py2.py3-none-manylinux1_i686.whl", hash = "sha256:636d07d90e68ccc9630c654d47ce9fdeb036bb46e2b193b3a9ac8cfea683cce5"}, + {file = "mkl-2021.4.0-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:398dbf2b0d12acaf54117a5210e8f191827f373d362d796091d161f610c1ebfb"}, + {file = "mkl-2021.4.0-py2.py3-none-win32.whl", hash = "sha256:439c640b269a5668134e3dcbcea4350459c4a8bc46469669b2d67e07e3d330e8"}, + {file = "mkl-2021.4.0-py2.py3-none-win_amd64.whl", hash = "sha256:ceef3cafce4c009dd25f65d7ad0d833a0fbadc3d8903991ec92351fe5de1e718"}, +] + +[package.dependencies] +intel-openmp = "==2021.*" +tbb = "==2021.*" + [[package]] name = "monotonic" version = "1.6" @@ -3978,44 +4139,44 @@ files = [ [[package]] name = "mypy" -version = "1.10.0" +version = "1.11.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da1cbf08fb3b851ab3b9523a884c232774008267b1f83371ace57f412fe308c2"}, - {file = "mypy-1.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:12b6bfc1b1a66095ab413160a6e520e1dc076a28f3e22f7fb25ba3b000b4ef99"}, - {file = "mypy-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e36fb078cce9904c7989b9693e41cb9711e0600139ce3970c6ef814b6ebc2b2"}, - {file = "mypy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2b0695d605ddcd3eb2f736cd8b4e388288c21e7de85001e9f85df9187f2b50f9"}, - {file = "mypy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:cd777b780312ddb135bceb9bc8722a73ec95e042f911cc279e2ec3c667076051"}, - {file = "mypy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3be66771aa5c97602f382230165b856c231d1277c511c9a8dd058be4784472e1"}, - {file = "mypy-1.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8b2cbaca148d0754a54d44121b5825ae71868c7592a53b7292eeb0f3fdae95ee"}, - {file = "mypy-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ec404a7cbe9fc0e92cb0e67f55ce0c025014e26d33e54d9e506a0f2d07fe5de"}, - {file = "mypy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e22e1527dc3d4aa94311d246b59e47f6455b8729f4968765ac1eacf9a4760bc7"}, - {file = "mypy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:a87dbfa85971e8d59c9cc1fcf534efe664d8949e4c0b6b44e8ca548e746a8d53"}, - {file = "mypy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a781f6ad4bab20eef8b65174a57e5203f4be627b46291f4589879bf4e257b97b"}, - {file = "mypy-1.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b808e12113505b97d9023b0b5e0c0705a90571c6feefc6f215c1df9381256e30"}, - {file = "mypy-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f55583b12156c399dce2df7d16f8a5095291354f1e839c252ec6c0611e86e2e"}, - {file = "mypy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cf18f9d0efa1b16478c4c129eabec36148032575391095f73cae2e722fcf9d5"}, - {file = "mypy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:bc6ac273b23c6b82da3bb25f4136c4fd42665f17f2cd850771cb600bdd2ebeda"}, - {file = "mypy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9fd50226364cd2737351c79807775136b0abe084433b55b2e29181a4c3c878c0"}, - {file = "mypy-1.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f90cff89eea89273727d8783fef5d4a934be2fdca11b47def50cf5d311aff727"}, - {file = "mypy-1.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcfc70599efde5c67862a07a1aaf50e55bce629ace26bb19dc17cece5dd31ca4"}, - {file = "mypy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:075cbf81f3e134eadaf247de187bd604748171d6b79736fa9b6c9685b4083061"}, - {file = "mypy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:3f298531bca95ff615b6e9f2fc0333aae27fa48052903a0ac90215021cdcfa4f"}, - {file = "mypy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa7ef5244615a2523b56c034becde4e9e3f9b034854c93639adb667ec9ec2976"}, - {file = "mypy-1.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3236a4c8f535a0631f85f5fcdffba71c7feeef76a6002fcba7c1a8e57c8be1ec"}, - {file = "mypy-1.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2b5cdbb5dd35aa08ea9114436e0d79aceb2f38e32c21684dcf8e24e1e92821"}, - {file = "mypy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92f93b21c0fe73dc00abf91022234c79d793318b8a96faac147cd579c1671746"}, - {file = "mypy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:28d0e038361b45f099cc086d9dd99c15ff14d0188f44ac883010e172ce86c38a"}, - {file = "mypy-1.10.0-py3-none-any.whl", hash = "sha256:f8c083976eb530019175aabadb60921e73b4f45736760826aa1689dda8208aee"}, - {file = "mypy-1.10.0.tar.gz", hash = "sha256:3d087fcbec056c4ee34974da493a826ce316947485cef3901f511848e687c131"}, + {file = "mypy-1.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3824187c99b893f90c845bab405a585d1ced4ff55421fdf5c84cb7710995229"}, + {file = "mypy-1.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96f8dbc2c85046c81bcddc246232d500ad729cb720da4e20fce3b542cab91287"}, + {file = "mypy-1.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a5d8d8dd8613a3e2be3eae829ee891b6b2de6302f24766ff06cb2875f5be9c6"}, + {file = "mypy-1.11.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72596a79bbfb195fd41405cffa18210af3811beb91ff946dbcb7368240eed6be"}, + {file = "mypy-1.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:35ce88b8ed3a759634cb4eb646d002c4cef0a38f20565ee82b5023558eb90c00"}, + {file = "mypy-1.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:98790025861cb2c3db8c2f5ad10fc8c336ed2a55f4daf1b8b3f877826b6ff2eb"}, + {file = "mypy-1.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:25bcfa75b9b5a5f8d67147a54ea97ed63a653995a82798221cca2a315c0238c1"}, + {file = "mypy-1.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bea2a0e71c2a375c9fa0ede3d98324214d67b3cbbfcbd55ac8f750f85a414e3"}, + {file = "mypy-1.11.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2b3d36baac48e40e3064d2901f2fbd2a2d6880ec6ce6358825c85031d7c0d4d"}, + {file = "mypy-1.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:d8e2e43977f0e09f149ea69fd0556623919f816764e26d74da0c8a7b48f3e18a"}, + {file = "mypy-1.11.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1d44c1e44a8be986b54b09f15f2c1a66368eb43861b4e82573026e04c48a9e20"}, + {file = "mypy-1.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cea3d0fb69637944dd321f41bc896e11d0fb0b0aa531d887a6da70f6e7473aba"}, + {file = "mypy-1.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a83ec98ae12d51c252be61521aa5731f5512231d0b738b4cb2498344f0b840cd"}, + {file = "mypy-1.11.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c7b73a856522417beb78e0fb6d33ef89474e7a622db2653bc1285af36e2e3e3d"}, + {file = "mypy-1.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:f2268d9fcd9686b61ab64f077be7ffbc6fbcdfb4103e5dd0cc5eaab53a8886c2"}, + {file = "mypy-1.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:940bfff7283c267ae6522ef926a7887305945f716a7704d3344d6d07f02df850"}, + {file = "mypy-1.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:14f9294528b5f5cf96c721f231c9f5b2733164e02c1c018ed1a0eff8a18005ac"}, + {file = "mypy-1.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7b54c27783991399046837df5c7c9d325d921394757d09dbcbf96aee4649fe9"}, + {file = "mypy-1.11.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:65f190a6349dec29c8d1a1cd4aa71284177aee5949e0502e6379b42873eddbe7"}, + {file = "mypy-1.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbe286303241fea8c2ea5466f6e0e6a046a135a7e7609167b07fd4e7baf151bf"}, + {file = "mypy-1.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:104e9c1620c2675420abd1f6c44bab7dd33cc85aea751c985006e83dcd001095"}, + {file = "mypy-1.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f006e955718ecd8d159cee9932b64fba8f86ee6f7728ca3ac66c3a54b0062abe"}, + {file = "mypy-1.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:becc9111ca572b04e7e77131bc708480cc88a911adf3d0239f974c034b78085c"}, + {file = "mypy-1.11.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6801319fe76c3f3a3833f2b5af7bd2c17bb93c00026a2a1b924e6762f5b19e13"}, + {file = "mypy-1.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:c1a184c64521dc549324ec6ef7cbaa6b351912be9cb5edb803c2808a0d7e85ac"}, + {file = "mypy-1.11.0-py3-none-any.whl", hash = "sha256:56913ec8c7638b0091ef4da6fcc9136896914a9d60d54670a75880c3e5b99ace"}, + {file = "mypy-1.11.0.tar.gz", hash = "sha256:93743608c7348772fdc717af4aeee1997293a1ad04bc0ea6efa15bf65385c538"}, ] [package.dependencies] mypy-extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=4.1.0" +typing-extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] @@ -4272,6 +4433,148 @@ files = [ {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, ] +[[package]] +name = "nvidia-cublas-cu12" +version = "12.1.3.1" +description = "CUBLAS native runtime libraries" +optional = false +python-versions = ">=3" +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"}, +] + +[[package]] +name = "nvidia-cuda-cupti-cu12" +version = "12.1.105" +description = "CUDA profiling tools runtime libs." +optional = false +python-versions = ">=3" +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"}, +] + +[[package]] +name = "nvidia-cuda-nvrtc-cu12" +version = "12.1.105" +description = "NVRTC native runtime libraries" +optional = false +python-versions = ">=3" +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"}, +] + +[[package]] +name = "nvidia-cuda-runtime-cu12" +version = "12.1.105" +description = "CUDA Runtime native Libraries" +optional = false +python-versions = ">=3" +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"}, +] + +[[package]] +name = "nvidia-cudnn-cu12" +version = "8.9.2.26" +description = "cuDNN runtime libraries" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_cudnn_cu12-8.9.2.26-py3-none-manylinux1_x86_64.whl", hash = "sha256:5ccb288774fdfb07a7e7025ffec286971c06d8d7b4fb162525334616d7629ff9"}, +] + +[package.dependencies] +nvidia-cublas-cu12 = "*" + +[[package]] +name = "nvidia-cufft-cu12" +version = "11.0.2.54" +description = "CUFFT native runtime libraries" +optional = false +python-versions = ">=3" +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"}, +] + +[[package]] +name = "nvidia-curand-cu12" +version = "10.3.2.106" +description = "CURAND native runtime libraries" +optional = false +python-versions = ">=3" +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"}, +] + +[[package]] +name = "nvidia-cusolver-cu12" +version = "11.4.5.107" +description = "CUDA solver native runtime libraries" +optional = false +python-versions = ">=3" +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"}, +] + +[package.dependencies] +nvidia-cublas-cu12 = "*" +nvidia-cusparse-cu12 = "*" +nvidia-nvjitlink-cu12 = "*" + +[[package]] +name = "nvidia-cusparse-cu12" +version = "12.1.0.106" +description = "CUSPARSE native runtime libraries" +optional = false +python-versions = ">=3" +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"}, +] + +[package.dependencies] +nvidia-nvjitlink-cu12 = "*" + +[[package]] +name = "nvidia-nccl-cu12" +version = "2.20.5" +description = "NVIDIA Collective Communication Library (NCCL) Runtime" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_nccl_cu12-2.20.5-py3-none-manylinux2014_aarch64.whl", hash = "sha256:1fc150d5c3250b170b29410ba682384b14581db722b2531b0d8d33c595f33d01"}, + {file = "nvidia_nccl_cu12-2.20.5-py3-none-manylinux2014_x86_64.whl", hash = "sha256:057f6bf9685f75215d0c53bf3ac4a10b3e6578351de307abad9e18a99182af56"}, +] + +[[package]] +name = "nvidia-nvjitlink-cu12" +version = "12.5.82" +description = "Nvidia JIT LTO Library" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_nvjitlink_cu12-12.5.82-py3-none-manylinux2014_x86_64.whl", hash = "sha256:f9b37bc5c8cf7509665cb6ada5aaa0ce65618f2332b7d3e78e9790511f111212"}, + {file = "nvidia_nvjitlink_cu12-12.5.82-py3-none-win_amd64.whl", hash = "sha256:e782564d705ff0bf61ac3e1bf730166da66dd2fe9012f111ede5fc49b64ae697"}, +] + +[[package]] +name = "nvidia-nvtx-cu12" +version = "12.1.105" +description = "NVIDIA Tools Extension" +optional = false +python-versions = ">=3" +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"}, +] + [[package]] name = "onnx" version = "1.16.1" @@ -4316,42 +4619,42 @@ reference = ["Pillow", "google-re2"] [[package]] name = "onnxruntime" -version = "1.18.0" +version = "1.18.1" description = "ONNX Runtime is a runtime accelerator for Machine Learning models" optional = false python-versions = "*" files = [ - {file = "onnxruntime-1.18.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:5a3b7993a5ecf4a90f35542a4757e29b2d653da3efe06cdd3164b91167bbe10d"}, - {file = "onnxruntime-1.18.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:15b944623b2cdfe7f7945690bfb71c10a4531b51997c8320b84e7b0bb59af902"}, - {file = "onnxruntime-1.18.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e61ce5005118064b1a0ed73ebe936bc773a102f067db34108ea6c64dd62a179"}, - {file = "onnxruntime-1.18.0-cp310-cp310-win32.whl", hash = "sha256:a4fc8a2a526eb442317d280610936a9f73deece06c7d5a91e51570860802b93f"}, - {file = "onnxruntime-1.18.0-cp310-cp310-win_amd64.whl", hash = "sha256:71ed219b768cab004e5cd83e702590734f968679bf93aa488c1a7ffbe6e220c3"}, - {file = "onnxruntime-1.18.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:3d24bd623872a72a7fe2f51c103e20fcca2acfa35d48f2accd6be1ec8633d960"}, - {file = "onnxruntime-1.18.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f15e41ca9b307a12550bfd2ec93f88905d9fba12bab7e578f05138ad0ae10d7b"}, - {file = "onnxruntime-1.18.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f45ca2887f62a7b847d526965686b2923efa72538c89b7703c7b3fe970afd59"}, - {file = "onnxruntime-1.18.0-cp311-cp311-win32.whl", hash = "sha256:9e24d9ecc8781323d9e2eeda019b4b24babc4d624e7d53f61b1fe1a929b0511a"}, - {file = "onnxruntime-1.18.0-cp311-cp311-win_amd64.whl", hash = "sha256:f8608398976ed18aef450d83777ff6f77d0b64eced1ed07a985e1a7db8ea3771"}, - {file = "onnxruntime-1.18.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:f1d79941f15fc40b1ee67738b2ca26b23e0181bf0070b5fb2984f0988734698f"}, - {file = "onnxruntime-1.18.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99e8caf3a8565c853a22d323a3eebc2a81e3de7591981f085a4f74f7a60aab2d"}, - {file = "onnxruntime-1.18.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:498d2b8380635f5e6ebc50ec1b45f181588927280f32390fb910301d234f97b8"}, - {file = "onnxruntime-1.18.0-cp312-cp312-win32.whl", hash = "sha256:ba7cc0ce2798a386c082aaa6289ff7e9bedc3dee622eef10e74830cff200a72e"}, - {file = "onnxruntime-1.18.0-cp312-cp312-win_amd64.whl", hash = "sha256:1fa175bd43f610465d5787ae06050c81f7ce09da2bf3e914eb282cb8eab363ef"}, - {file = "onnxruntime-1.18.0-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:0284c579c20ec8b1b472dd190290a040cc68b6caec790edb960f065d15cf164a"}, - {file = "onnxruntime-1.18.0-cp38-cp38-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d47353d036d8c380558a5643ea5f7964d9d259d31c86865bad9162c3e916d1f6"}, - {file = "onnxruntime-1.18.0-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:885509d2b9ba4b01f08f7fa28d31ee54b6477953451c7ccf124a84625f07c803"}, - {file = "onnxruntime-1.18.0-cp38-cp38-win32.whl", hash = "sha256:8614733de3695656411d71fc2f39333170df5da6c7efd6072a59962c0bc7055c"}, - {file = "onnxruntime-1.18.0-cp38-cp38-win_amd64.whl", hash = "sha256:47af3f803752fce23ea790fd8d130a47b2b940629f03193f780818622e856e7a"}, - {file = "onnxruntime-1.18.0-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:9153eb2b4d5bbab764d0aea17adadffcfc18d89b957ad191b1c3650b9930c59f"}, - {file = "onnxruntime-1.18.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c7fd86eca727c989bb8d9c5104f3c45f7ee45f445cc75579ebe55d6b99dfd7c"}, - {file = "onnxruntime-1.18.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ac67a4de9c1326c4d87bcbfb652c923039b8a2446bb28516219236bec3b494f5"}, - {file = "onnxruntime-1.18.0-cp39-cp39-win32.whl", hash = "sha256:6ffb445816d06497df7a6dd424b20e0b2c39639e01e7fe210e247b82d15a23b9"}, - {file = "onnxruntime-1.18.0-cp39-cp39-win_amd64.whl", hash = "sha256:46de6031cb6745f33f7eca9e51ab73e8c66037fb7a3b6b4560887c5b55ab5d5d"}, + {file = "onnxruntime-1.18.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:29ef7683312393d4ba04252f1b287d964bd67d5e6048b94d2da3643986c74d80"}, + {file = "onnxruntime-1.18.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fc706eb1df06ddf55776e15a30519fb15dda7697f987a2bbda4962845e3cec05"}, + {file = "onnxruntime-1.18.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7de69f5ced2a263531923fa68bbec52a56e793b802fcd81a03487b5e292bc3a"}, + {file = "onnxruntime-1.18.1-cp310-cp310-win32.whl", hash = "sha256:221e5b16173926e6c7de2cd437764492aa12b6811f45abd37024e7cf2ae5d7e3"}, + {file = "onnxruntime-1.18.1-cp310-cp310-win_amd64.whl", hash = "sha256:75211b619275199c861ee94d317243b8a0fcde6032e5a80e1aa9ded8ab4c6060"}, + {file = "onnxruntime-1.18.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:f26582882f2dc581b809cfa41a125ba71ad9e715738ec6402418df356969774a"}, + {file = "onnxruntime-1.18.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef36f3a8b768506d02be349ac303fd95d92813ba3ba70304d40c3cd5c25d6a4c"}, + {file = "onnxruntime-1.18.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:170e711393e0618efa8ed27b59b9de0ee2383bd2a1f93622a97006a5ad48e434"}, + {file = "onnxruntime-1.18.1-cp311-cp311-win32.whl", hash = "sha256:9b6a33419b6949ea34e0dc009bc4470e550155b6da644571ecace4b198b0d88f"}, + {file = "onnxruntime-1.18.1-cp311-cp311-win_amd64.whl", hash = "sha256:5c1380a9f1b7788da742c759b6a02ba771fe1ce620519b2b07309decbd1a2fe1"}, + {file = "onnxruntime-1.18.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:31bd57a55e3f983b598675dfc7e5d6f0877b70ec9864b3cc3c3e1923d0a01919"}, + {file = "onnxruntime-1.18.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9e03c4ba9f734500691a4d7d5b381cd71ee2f3ce80a1154ac8f7aed99d1ecaa"}, + {file = "onnxruntime-1.18.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:781aa9873640f5df24524f96f6070b8c550c66cb6af35710fd9f92a20b4bfbf6"}, + {file = "onnxruntime-1.18.1-cp312-cp312-win32.whl", hash = "sha256:3a2d9ab6254ca62adbb448222e630dc6883210f718065063518c8f93a32432be"}, + {file = "onnxruntime-1.18.1-cp312-cp312-win_amd64.whl", hash = "sha256:ad93c560b1c38c27c0275ffd15cd7f45b3ad3fc96653c09ce2931179982ff204"}, + {file = "onnxruntime-1.18.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:3b55dc9d3c67626388958a3eb7ad87eb7c70f75cb0f7ff4908d27b8b42f2475c"}, + {file = "onnxruntime-1.18.1-cp38-cp38-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f80dbcfb6763cc0177a31168b29b4bd7662545b99a19e211de8c734b657e0669"}, + {file = "onnxruntime-1.18.1-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f1ff2c61a16d6c8631796c54139bafea41ee7736077a0fc64ee8ae59432f5c58"}, + {file = "onnxruntime-1.18.1-cp38-cp38-win32.whl", hash = "sha256:219855bd272fe0c667b850bf1a1a5a02499269a70d59c48e6f27f9c8bcb25d02"}, + {file = "onnxruntime-1.18.1-cp38-cp38-win_amd64.whl", hash = "sha256:afdf16aa607eb9a2c60d5ca2d5abf9f448e90c345b6b94c3ed14f4fb7e6a2d07"}, + {file = "onnxruntime-1.18.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:128df253ade673e60cea0955ec9d0e89617443a6d9ce47c2d79eb3f72a3be3de"}, + {file = "onnxruntime-1.18.1-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9839491e77e5c5a175cab3621e184d5a88925ee297ff4c311b68897197f4cde9"}, + {file = "onnxruntime-1.18.1-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad3187c1faff3ac15f7f0e7373ef4788c582cafa655a80fdbb33eaec88976c66"}, + {file = "onnxruntime-1.18.1-cp39-cp39-win32.whl", hash = "sha256:34657c78aa4e0b5145f9188b550ded3af626651b15017bf43d280d7e23dbf195"}, + {file = "onnxruntime-1.18.1-cp39-cp39-win_amd64.whl", hash = "sha256:9c14fd97c3ddfa97da5feef595e2c73f14c2d0ec1d4ecbea99c8d96603c89589"}, ] [package.dependencies] coloredlogs = "*" flatbuffers = "*" -numpy = ">=1.21.6" +numpy = ">=1.21.6,<2.0" packaging = "*" protobuf = "*" sympy = "*" @@ -4381,61 +4684,62 @@ datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] [[package]] name = "orjson" -version = "3.9.10" +version = "3.10.6" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false python-versions = ">=3.8" files = [ - {file = "orjson-3.9.10-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c18a4da2f50050a03d1da5317388ef84a16013302a5281d6f64e4a3f406aabc4"}, - {file = "orjson-3.9.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5148bab4d71f58948c7c39d12b14a9005b6ab35a0bdf317a8ade9a9e4d9d0bd5"}, - {file = "orjson-3.9.10-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4cf7837c3b11a2dfb589f8530b3cff2bd0307ace4c301e8997e95c7468c1378e"}, - {file = "orjson-3.9.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c62b6fa2961a1dcc51ebe88771be5319a93fd89bd247c9ddf732bc250507bc2b"}, - {file = "orjson-3.9.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:deeb3922a7a804755bbe6b5be9b312e746137a03600f488290318936c1a2d4dc"}, - {file = "orjson-3.9.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1234dc92d011d3554d929b6cf058ac4a24d188d97be5e04355f1b9223e98bbe9"}, - {file = "orjson-3.9.10-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:06ad5543217e0e46fd7ab7ea45d506c76f878b87b1b4e369006bdb01acc05a83"}, - {file = "orjson-3.9.10-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4fd72fab7bddce46c6826994ce1e7de145ae1e9e106ebb8eb9ce1393ca01444d"}, - {file = "orjson-3.9.10-cp310-none-win32.whl", hash = "sha256:b5b7d4a44cc0e6ff98da5d56cde794385bdd212a86563ac321ca64d7f80c80d1"}, - {file = "orjson-3.9.10-cp310-none-win_amd64.whl", hash = "sha256:61804231099214e2f84998316f3238c4c2c4aaec302df12b21a64d72e2a135c7"}, - {file = "orjson-3.9.10-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:cff7570d492bcf4b64cc862a6e2fb77edd5e5748ad715f487628f102815165e9"}, - {file = "orjson-3.9.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed8bc367f725dfc5cabeed1ae079d00369900231fbb5a5280cf0736c30e2adf7"}, - {file = "orjson-3.9.10-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c812312847867b6335cfb264772f2a7e85b3b502d3a6b0586aa35e1858528ab1"}, - {file = "orjson-3.9.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edd2856611e5050004f4722922b7b1cd6268da34102667bd49d2a2b18bafb81"}, - {file = "orjson-3.9.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:674eb520f02422546c40401f4efaf8207b5e29e420c17051cddf6c02783ff5ca"}, - {file = "orjson-3.9.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d0dc4310da8b5f6415949bd5ef937e60aeb0eb6b16f95041b5e43e6200821fb"}, - {file = "orjson-3.9.10-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e99c625b8c95d7741fe057585176b1b8783d46ed4b8932cf98ee145c4facf499"}, - {file = "orjson-3.9.10-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ec6f18f96b47299c11203edfbdc34e1b69085070d9a3d1f302810cc23ad36bf3"}, - {file = "orjson-3.9.10-cp311-none-win32.whl", hash = "sha256:ce0a29c28dfb8eccd0f16219360530bc3cfdf6bf70ca384dacd36e6c650ef8e8"}, - {file = "orjson-3.9.10-cp311-none-win_amd64.whl", hash = "sha256:cf80b550092cc480a0cbd0750e8189247ff45457e5a023305f7ef1bcec811616"}, - {file = "orjson-3.9.10-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:602a8001bdf60e1a7d544be29c82560a7b49319a0b31d62586548835bbe2c862"}, - {file = "orjson-3.9.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f295efcd47b6124b01255d1491f9e46f17ef40d3d7eabf7364099e463fb45f0f"}, - {file = "orjson-3.9.10-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:92af0d00091e744587221e79f68d617b432425a7e59328ca4c496f774a356071"}, - {file = "orjson-3.9.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5a02360e73e7208a872bf65a7554c9f15df5fe063dc047f79738998b0506a14"}, - {file = "orjson-3.9.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:858379cbb08d84fe7583231077d9a36a1a20eb72f8c9076a45df8b083724ad1d"}, - {file = "orjson-3.9.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666c6fdcaac1f13eb982b649e1c311c08d7097cbda24f32612dae43648d8db8d"}, - {file = "orjson-3.9.10-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3fb205ab52a2e30354640780ce4587157a9563a68c9beaf52153e1cea9aa0921"}, - {file = "orjson-3.9.10-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7ec960b1b942ee3c69323b8721df2a3ce28ff40e7ca47873ae35bfafeb4555ca"}, - {file = "orjson-3.9.10-cp312-none-win_amd64.whl", hash = "sha256:3e892621434392199efb54e69edfff9f699f6cc36dd9553c5bf796058b14b20d"}, - {file = "orjson-3.9.10-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:8b9ba0ccd5a7f4219e67fbbe25e6b4a46ceef783c42af7dbc1da548eb28b6531"}, - {file = "orjson-3.9.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e2ecd1d349e62e3960695214f40939bbfdcaeaaa62ccc638f8e651cf0970e5f"}, - {file = "orjson-3.9.10-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f433be3b3f4c66016d5a20e5b4444ef833a1f802ced13a2d852c637f69729c1"}, - {file = "orjson-3.9.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4689270c35d4bb3102e103ac43c3f0b76b169760aff8bcf2d401a3e0e58cdb7f"}, - {file = "orjson-3.9.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4bd176f528a8151a6efc5359b853ba3cc0e82d4cd1fab9c1300c5d957dc8f48c"}, - {file = "orjson-3.9.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a2ce5ea4f71681623f04e2b7dadede3c7435dfb5e5e2d1d0ec25b35530e277b"}, - {file = "orjson-3.9.10-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:49f8ad582da6e8d2cf663c4ba5bf9f83cc052570a3a767487fec6af839b0e777"}, - {file = "orjson-3.9.10-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2a11b4b1a8415f105d989876a19b173f6cdc89ca13855ccc67c18efbd7cbd1f8"}, - {file = "orjson-3.9.10-cp38-none-win32.whl", hash = "sha256:a353bf1f565ed27ba71a419b2cd3db9d6151da426b61b289b6ba1422a702e643"}, - {file = "orjson-3.9.10-cp38-none-win_amd64.whl", hash = "sha256:e28a50b5be854e18d54f75ef1bb13e1abf4bc650ab9d635e4258c58e71eb6ad5"}, - {file = "orjson-3.9.10-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ee5926746232f627a3be1cc175b2cfad24d0170d520361f4ce3fa2fd83f09e1d"}, - {file = "orjson-3.9.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a73160e823151f33cdc05fe2cea557c5ef12fdf276ce29bb4f1c571c8368a60"}, - {file = "orjson-3.9.10-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c338ed69ad0b8f8f8920c13f529889fe0771abbb46550013e3c3d01e5174deef"}, - {file = "orjson-3.9.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5869e8e130e99687d9e4be835116c4ebd83ca92e52e55810962446d841aba8de"}, - {file = "orjson-3.9.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2c1e559d96a7f94a4f581e2a32d6d610df5840881a8cba8f25e446f4d792df3"}, - {file = "orjson-3.9.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a3a3a72c9811b56adf8bcc829b010163bb2fc308877e50e9910c9357e78521"}, - {file = "orjson-3.9.10-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7f8fb7f5ecf4f6355683ac6881fd64b5bb2b8a60e3ccde6ff799e48791d8f864"}, - {file = "orjson-3.9.10-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c943b35ecdf7123b2d81d225397efddf0bce2e81db2f3ae633ead38e85cd5ade"}, - {file = "orjson-3.9.10-cp39-none-win32.whl", hash = "sha256:fb0b361d73f6b8eeceba47cd37070b5e6c9de5beaeaa63a1cb35c7e1a73ef088"}, - {file = "orjson-3.9.10-cp39-none-win_amd64.whl", hash = "sha256:b90f340cb6397ec7a854157fac03f0c82b744abdd1c0941a024c3c29d1340aff"}, - {file = "orjson-3.9.10.tar.gz", hash = "sha256:9ebbdbd6a046c304b1845e96fbcc5559cd296b4dfd3ad2509e33c4d9ce07d6a1"}, + {file = "orjson-3.10.6-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:fb0ee33124db6eaa517d00890fc1a55c3bfe1cf78ba4a8899d71a06f2d6ff5c7"}, + {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c1c4b53b24a4c06547ce43e5fee6ec4e0d8fe2d597f4647fc033fd205707365"}, + {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eadc8fd310edb4bdbd333374f2c8fec6794bbbae99b592f448d8214a5e4050c0"}, + {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61272a5aec2b2661f4fa2b37c907ce9701e821b2c1285d5c3ab0207ebd358d38"}, + {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57985ee7e91d6214c837936dc1608f40f330a6b88bb13f5a57ce5257807da143"}, + {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:633a3b31d9d7c9f02d49c4ab4d0a86065c4a6f6adc297d63d272e043472acab5"}, + {file = "orjson-3.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1c680b269d33ec444afe2bdc647c9eb73166fa47a16d9a75ee56a374f4a45f43"}, + {file = "orjson-3.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f759503a97a6ace19e55461395ab0d618b5a117e8d0fbb20e70cfd68a47327f2"}, + {file = "orjson-3.10.6-cp310-none-win32.whl", hash = "sha256:95a0cce17f969fb5391762e5719575217bd10ac5a189d1979442ee54456393f3"}, + {file = "orjson-3.10.6-cp310-none-win_amd64.whl", hash = "sha256:df25d9271270ba2133cc88ee83c318372bdc0f2cd6f32e7a450809a111efc45c"}, + {file = "orjson-3.10.6-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b1ec490e10d2a77c345def52599311849fc063ae0e67cf4f84528073152bb2ba"}, + {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d43d3feb8f19d07e9f01e5b9be4f28801cf7c60d0fa0d279951b18fae1932b"}, + {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3045267e98fe749408eee1593a142e02357c5c99be0802185ef2170086a863"}, + {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c27bc6a28ae95923350ab382c57113abd38f3928af3c80be6f2ba7eb8d8db0b0"}, + {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d27456491ca79532d11e507cadca37fb8c9324a3976294f68fb1eff2dc6ced5a"}, + {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05ac3d3916023745aa3b3b388e91b9166be1ca02b7c7e41045da6d12985685f0"}, + {file = "orjson-3.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1335d4ef59ab85cab66fe73fd7a4e881c298ee7f63ede918b7faa1b27cbe5212"}, + {file = "orjson-3.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4bbc6d0af24c1575edc79994c20e1b29e6fb3c6a570371306db0993ecf144dc5"}, + {file = "orjson-3.10.6-cp311-none-win32.whl", hash = "sha256:450e39ab1f7694465060a0550b3f6d328d20297bf2e06aa947b97c21e5241fbd"}, + {file = "orjson-3.10.6-cp311-none-win_amd64.whl", hash = "sha256:227df19441372610b20e05bdb906e1742ec2ad7a66ac8350dcfd29a63014a83b"}, + {file = "orjson-3.10.6-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ea2977b21f8d5d9b758bb3f344a75e55ca78e3ff85595d248eee813ae23ecdfb"}, + {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b6f3d167d13a16ed263b52dbfedff52c962bfd3d270b46b7518365bcc2121eed"}, + {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f710f346e4c44a4e8bdf23daa974faede58f83334289df80bc9cd12fe82573c7"}, + {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7275664f84e027dcb1ad5200b8b18373e9c669b2a9ec33d410c40f5ccf4b257e"}, + {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0943e4c701196b23c240b3d10ed8ecd674f03089198cf503105b474a4f77f21f"}, + {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:446dee5a491b5bc7d8f825d80d9637e7af43f86a331207b9c9610e2f93fee22a"}, + {file = "orjson-3.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:64c81456d2a050d380786413786b057983892db105516639cb5d3ee3c7fd5148"}, + {file = "orjson-3.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:960db0e31c4e52fa0fc3ecbaea5b2d3b58f379e32a95ae6b0ebeaa25b93dfd34"}, + {file = "orjson-3.10.6-cp312-none-win32.whl", hash = "sha256:a6ea7afb5b30b2317e0bee03c8d34c8181bc5a36f2afd4d0952f378972c4efd5"}, + {file = "orjson-3.10.6-cp312-none-win_amd64.whl", hash = "sha256:874ce88264b7e655dde4aeaacdc8fd772a7962faadfb41abe63e2a4861abc3dc"}, + {file = "orjson-3.10.6-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:66680eae4c4e7fc193d91cfc1353ad6d01b4801ae9b5314f17e11ba55e934183"}, + {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:caff75b425db5ef8e8f23af93c80f072f97b4fb3afd4af44482905c9f588da28"}, + {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3722fddb821b6036fd2a3c814f6bd9b57a89dc6337b9924ecd614ebce3271394"}, + {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2c116072a8533f2fec435fde4d134610f806bdac20188c7bd2081f3e9e0133f"}, + {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6eeb13218c8cf34c61912e9df2de2853f1d009de0e46ea09ccdf3d757896af0a"}, + {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:965a916373382674e323c957d560b953d81d7a8603fbeee26f7b8248638bd48b"}, + {file = "orjson-3.10.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:03c95484d53ed8e479cade8628c9cea00fd9d67f5554764a1110e0d5aa2de96e"}, + {file = "orjson-3.10.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:e060748a04cccf1e0a6f2358dffea9c080b849a4a68c28b1b907f272b5127e9b"}, + {file = "orjson-3.10.6-cp38-none-win32.whl", hash = "sha256:738dbe3ef909c4b019d69afc19caf6b5ed0e2f1c786b5d6215fbb7539246e4c6"}, + {file = "orjson-3.10.6-cp38-none-win_amd64.whl", hash = "sha256:d40f839dddf6a7d77114fe6b8a70218556408c71d4d6e29413bb5f150a692ff7"}, + {file = "orjson-3.10.6-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:697a35a083c4f834807a6232b3e62c8b280f7a44ad0b759fd4dce748951e70db"}, + {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd502f96bf5ea9a61cbc0b2b5900d0dd68aa0da197179042bdd2be67e51a1e4b"}, + {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f215789fb1667cdc874c1b8af6a84dc939fd802bf293a8334fce185c79cd359b"}, + {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2debd8ddce948a8c0938c8c93ade191d2f4ba4649a54302a7da905a81f00b56"}, + {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5410111d7b6681d4b0d65e0f58a13be588d01b473822483f77f513c7f93bd3b2"}, + {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb1f28a137337fdc18384079fa5726810681055b32b92253fa15ae5656e1dddb"}, + {file = "orjson-3.10.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bf2fbbce5fe7cd1aa177ea3eab2b8e6a6bc6e8592e4279ed3db2d62e57c0e1b2"}, + {file = "orjson-3.10.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:79b9b9e33bd4c517445a62b90ca0cc279b0f1f3970655c3df9e608bc3f91741a"}, + {file = "orjson-3.10.6-cp39-none-win32.whl", hash = "sha256:30b0a09a2014e621b1adf66a4f705f0809358350a757508ee80209b2d8dae219"}, + {file = "orjson-3.10.6-cp39-none-win_amd64.whl", hash = "sha256:49e3bc615652617d463069f91b867a4458114c5b104e13b7ae6872e5f79d0844"}, + {file = "orjson-3.10.6.tar.gz", hash = "sha256:e54b63d0a7c6c54a5f5f726bc93a2078111ef060fec4ecbf34c5db800ca3b3a7"}, ] [[package]] @@ -4600,6 +4904,42 @@ files = [ docs = ["Sphinx (>=2.4)", "sphinx-rtd-theme (>=1.2.2)", "urllib3 (<2)"] test = ["Faker (>=1.0.8)", "allpairspy (>=2)", "click (>=6.2)", "pytest (>=6.0.1)", "pytest-discord (>=0.1.4)", "pytest-md-report (>=0.4.1)"] +[[package]] +name = "pdfminer-six" +version = "20231228" +description = "PDF parser and analyzer" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pdfminer.six-20231228-py3-none-any.whl", hash = "sha256:e8d3c3310e6fbc1fe414090123ab01351634b4ecb021232206c4c9a8ca3e3b8f"}, + {file = "pdfminer.six-20231228.tar.gz", hash = "sha256:6004da3ad1a7a4d45930cb950393df89b068e73be365a6ff64a838d37bcb08c4"}, +] + +[package.dependencies] +charset-normalizer = ">=2.0.0" +cryptography = ">=36.0.0" + +[package.extras] +dev = ["black", "mypy (==0.931)", "nox", "pytest"] +docs = ["sphinx", "sphinx-argparse"] +image = ["Pillow"] + +[[package]] +name = "pdfplumber" +version = "0.11.2" +description = "Plumb a PDF for detailed information about each char, rectangle, and line." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pdfplumber-0.11.2-py3-none-any.whl", hash = "sha256:024a7e0f8f4e7bbec8e1f6f694faeaa7b9fe33a0c1f9edd9d3f77298d9146b87"}, + {file = "pdfplumber-0.11.2.tar.gz", hash = "sha256:f237ce88e9918358f3848f4bae469358ca121ca412098e370908878ec9da699a"}, +] + +[package.dependencies] +"pdfminer.six" = "20231228" +Pillow = ">=9.1" +pypdfium2 = ">=4.18.0" + [[package]] name = "pendulum" version = "3.0.0" @@ -4715,84 +5055,95 @@ ptyprocess = ">=0.5" [[package]] name = "pillow" -version = "10.3.0" +version = "10.4.0" description = "Python Imaging Library (Fork)" optional = false python-versions = ">=3.8" files = [ - {file = "pillow-10.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45"}, - {file = "pillow-10.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c"}, - {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf"}, - {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599"}, - {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475"}, - {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf"}, - {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3"}, - {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5"}, - {file = "pillow-10.3.0-cp310-cp310-win32.whl", hash = "sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2"}, - {file = "pillow-10.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f"}, - {file = "pillow-10.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b"}, - {file = "pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795"}, - {file = "pillow-10.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57"}, - {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27"}, - {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994"}, - {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451"}, - {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd"}, - {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad"}, - {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c"}, - {file = "pillow-10.3.0-cp311-cp311-win32.whl", hash = "sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09"}, - {file = "pillow-10.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d"}, - {file = "pillow-10.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f"}, - {file = "pillow-10.3.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84"}, - {file = "pillow-10.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19"}, - {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338"}, - {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1"}, - {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462"}, - {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a"}, - {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef"}, - {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3"}, - {file = "pillow-10.3.0-cp312-cp312-win32.whl", hash = "sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d"}, - {file = "pillow-10.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b"}, - {file = "pillow-10.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a"}, - {file = "pillow-10.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b"}, - {file = "pillow-10.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2"}, - {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa"}, - {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383"}, - {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d"}, - {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd"}, - {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d"}, - {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3"}, - {file = "pillow-10.3.0-cp38-cp38-win32.whl", hash = "sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b"}, - {file = "pillow-10.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999"}, - {file = "pillow-10.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936"}, - {file = "pillow-10.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002"}, - {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60"}, - {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375"}, - {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57"}, - {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8"}, - {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9"}, - {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb"}, - {file = "pillow-10.3.0-cp39-cp39-win32.whl", hash = "sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572"}, - {file = "pillow-10.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb"}, - {file = "pillow-10.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f"}, - {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355"}, - {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9"}, - {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2"}, - {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463"}, - {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced"}, - {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3"}, - {file = "pillow-10.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170"}, - {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32"}, - {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828"}, - {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f"}, - {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015"}, - {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5"}, - {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a"}, - {file = "pillow-10.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591"}, - {file = "pillow-10.3.0.tar.gz", hash = "sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d"}, + {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"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc"}, + {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e"}, + {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46"}, + {file = "pillow-10.4.0-cp310-cp310-win32.whl", hash = "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984"}, + {file = "pillow-10.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141"}, + {file = "pillow-10.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1"}, + {file = "pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c"}, + {file = "pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319"}, + {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d"}, + {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696"}, + {file = "pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496"}, + {file = "pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91"}, + {file = "pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22"}, + {file = "pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94"}, + {file = "pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a"}, + {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b"}, + {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9"}, + {file = "pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42"}, + {file = "pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a"}, + {file = "pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9"}, + {file = "pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3"}, + {file = "pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc"}, + {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a"}, + {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309"}, + {file = "pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060"}, + {file = "pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea"}, + {file = "pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d"}, + {file = "pillow-10.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736"}, + {file = "pillow-10.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd"}, + {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84"}, + {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0"}, + {file = "pillow-10.4.0-cp38-cp38-win32.whl", hash = "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e"}, + {file = "pillow-10.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab"}, + {file = "pillow-10.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d"}, + {file = "pillow-10.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c"}, + {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1"}, + {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df"}, + {file = "pillow-10.4.0-cp39-cp39-win32.whl", hash = "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef"}, + {file = "pillow-10.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5"}, + {file = "pillow-10.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3"}, + {file = "pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06"}, ] [package.extras] -docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +docs = ["furo", "olefile", "sphinx (>=7.3)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] fpx = ["olefile"] mic = ["olefile"] tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] @@ -4843,13 +5194,13 @@ files = [ [[package]] name = "portalocker" -version = "2.8.2" +version = "2.10.1" description = "Wraps the portalocker recipe for easy usage" optional = false python-versions = ">=3.8" files = [ - {file = "portalocker-2.8.2-py3-none-any.whl", hash = "sha256:cfb86acc09b9aa7c3b43594e19be1345b9d16af3feb08bf92f23d4dce513a28e"}, - {file = "portalocker-2.8.2.tar.gz", hash = "sha256:2b035aa7828e46c58e9b31390ee1f169b98e1066ab10b9a6a861fe7e25ee4f33"}, + {file = "portalocker-2.10.1-py3-none-any.whl", hash = "sha256:53a5984ebc86a025552264b459b46a2086e269b21823cb572f8f28ee759e45bf"}, + {file = "portalocker-2.10.1.tar.gz", hash = "sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f"}, ] [package.dependencies] @@ -4945,13 +5296,13 @@ twisted = ["twisted"] [[package]] name = "prompt-toolkit" -version = "3.0.46" +version = "3.0.47" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.46-py3-none-any.whl", hash = "sha256:45abe60a8300f3c618b23c16c4bb98c6fc80af8ce8b17c7ae92db48db3ee63c1"}, - {file = "prompt_toolkit-3.0.46.tar.gz", hash = "sha256:869c50d682152336e23c4db7f74667639b5047494202ffe7670817053fd57795"}, + {file = "prompt_toolkit-3.0.47-py3-none-any.whl", hash = "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10"}, + {file = "prompt_toolkit-3.0.47.tar.gz", hash = "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360"}, ] [package.dependencies] @@ -4979,27 +5330,28 @@ files = [ [[package]] name = "psutil" -version = "5.9.8" +version = "6.0.0" description = "Cross-platform lib for process and system monitoring in Python." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ - {file = "psutil-5.9.8-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8"}, - {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73"}, - {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7"}, - {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36"}, - {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d"}, - {file = "psutil-5.9.8-cp27-none-win32.whl", hash = "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e"}, - {file = "psutil-5.9.8-cp27-none-win_amd64.whl", hash = "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631"}, - {file = "psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81"}, - {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421"}, - {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4"}, - {file = "psutil-5.9.8-cp36-cp36m-win32.whl", hash = "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee"}, - {file = "psutil-5.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2"}, - {file = "psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0"}, - {file = "psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf"}, - {file = "psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8"}, - {file = "psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c"}, + {file = "psutil-6.0.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a021da3e881cd935e64a3d0a20983bda0bb4cf80e4f74fa9bfcb1bc5785360c6"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1287c2b95f1c0a364d23bc6f2ea2365a8d4d9b726a3be7294296ff7ba97c17f0"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a9a3dbfb4de4f18174528d87cc352d1f788b7496991cca33c6996f40c9e3c92c"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6ec7588fb3ddaec7344a825afe298db83fe01bfaaab39155fa84cf1c0d6b13c3"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e7c870afcb7d91fdea2b37c24aeb08f98b6d67257a5cb0a8bc3ac68d0f1a68c"}, + {file = "psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35"}, + {file = "psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1"}, + {file = "psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132"}, + {file = "psutil-6.0.0-cp36-cp36m-win32.whl", hash = "sha256:fc8c9510cde0146432bbdb433322861ee8c3efbf8589865c8bf8d21cb30c4d14"}, + {file = "psutil-6.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:34859b8d8f423b86e4385ff3665d3f4d94be3cdf48221fbe476e883514fdb71c"}, + {file = "psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d"}, + {file = "psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3"}, + {file = "psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0"}, + {file = "psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2"}, ] [package.extras] @@ -5102,109 +5454,119 @@ files = [ [[package]] name = "pydantic" -version = "2.7.0" +version = "2.8.2" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.7.0-py3-none-any.whl", hash = "sha256:9dee74a271705f14f9a1567671d144a851c675b072736f0a7b2608fd9e495352"}, - {file = "pydantic-2.7.0.tar.gz", hash = "sha256:b5ecdd42262ca2462e2624793551e80911a1e989f462910bb81aef974b4bb383"}, + {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"}, + {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"}, ] [package.dependencies] annotated-types = ">=0.4.0" -pydantic-core = "2.18.1" -typing-extensions = ">=4.6.1" +pydantic-core = "2.20.1" +typing-extensions = {version = ">=4.6.1", markers = "python_version < \"3.13\""} [package.extras] email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.18.1" +version = "2.20.1" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.18.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:ee9cf33e7fe14243f5ca6977658eb7d1042caaa66847daacbd2117adb258b226"}, - {file = "pydantic_core-2.18.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6b7bbb97d82659ac8b37450c60ff2e9f97e4eb0f8a8a3645a5568b9334b08b50"}, - {file = "pydantic_core-2.18.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df4249b579e75094f7e9bb4bd28231acf55e308bf686b952f43100a5a0be394c"}, - {file = "pydantic_core-2.18.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d0491006a6ad20507aec2be72e7831a42efc93193d2402018007ff827dc62926"}, - {file = "pydantic_core-2.18.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ae80f72bb7a3e397ab37b53a2b49c62cc5496412e71bc4f1277620a7ce3f52b"}, - {file = "pydantic_core-2.18.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:58aca931bef83217fca7a390e0486ae327c4af9c3e941adb75f8772f8eeb03a1"}, - {file = "pydantic_core-2.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1be91ad664fc9245404a789d60cba1e91c26b1454ba136d2a1bf0c2ac0c0505a"}, - {file = "pydantic_core-2.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:667880321e916a8920ef49f5d50e7983792cf59f3b6079f3c9dac2b88a311d17"}, - {file = "pydantic_core-2.18.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f7054fdc556f5421f01e39cbb767d5ec5c1139ea98c3e5b350e02e62201740c7"}, - {file = "pydantic_core-2.18.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:030e4f9516f9947f38179249778709a460a3adb516bf39b5eb9066fcfe43d0e6"}, - {file = "pydantic_core-2.18.1-cp310-none-win32.whl", hash = "sha256:2e91711e36e229978d92642bfc3546333a9127ecebb3f2761372e096395fc649"}, - {file = "pydantic_core-2.18.1-cp310-none-win_amd64.whl", hash = "sha256:9a29726f91c6cb390b3c2338f0df5cd3e216ad7a938762d11c994bb37552edb0"}, - {file = "pydantic_core-2.18.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:9ece8a49696669d483d206b4474c367852c44815fca23ac4e48b72b339807f80"}, - {file = "pydantic_core-2.18.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a5d83efc109ceddb99abd2c1316298ced2adb4570410defe766851a804fcd5b"}, - {file = "pydantic_core-2.18.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7973c381283783cd1043a8c8f61ea5ce7a3a58b0369f0ee0ee975eaf2f2a1b"}, - {file = "pydantic_core-2.18.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:54c7375c62190a7845091f521add19b0f026bcf6ae674bdb89f296972272e86d"}, - {file = "pydantic_core-2.18.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd63cec4e26e790b70544ae5cc48d11b515b09e05fdd5eff12e3195f54b8a586"}, - {file = "pydantic_core-2.18.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:561cf62c8a3498406495cfc49eee086ed2bb186d08bcc65812b75fda42c38294"}, - {file = "pydantic_core-2.18.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68717c38a68e37af87c4da20e08f3e27d7e4212e99e96c3d875fbf3f4812abfc"}, - {file = "pydantic_core-2.18.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d5728e93d28a3c63ee513d9ffbac9c5989de8c76e049dbcb5bfe4b923a9739d"}, - {file = "pydantic_core-2.18.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f0f17814c505f07806e22b28856c59ac80cee7dd0fbb152aed273e116378f519"}, - {file = "pydantic_core-2.18.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d816f44a51ba5175394bc6c7879ca0bd2be560b2c9e9f3411ef3a4cbe644c2e9"}, - {file = "pydantic_core-2.18.1-cp311-none-win32.whl", hash = "sha256:09f03dfc0ef8c22622eaa8608caa4a1e189cfb83ce847045eca34f690895eccb"}, - {file = "pydantic_core-2.18.1-cp311-none-win_amd64.whl", hash = "sha256:27f1009dc292f3b7ca77feb3571c537276b9aad5dd4efb471ac88a8bd09024e9"}, - {file = "pydantic_core-2.18.1-cp311-none-win_arm64.whl", hash = "sha256:48dd883db92e92519201f2b01cafa881e5f7125666141a49ffba8b9facc072b0"}, - {file = "pydantic_core-2.18.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b6b0e4912030c6f28bcb72b9ebe4989d6dc2eebcd2a9cdc35fefc38052dd4fe8"}, - {file = "pydantic_core-2.18.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3202a429fe825b699c57892d4371c74cc3456d8d71b7f35d6028c96dfecad31"}, - {file = "pydantic_core-2.18.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3982b0a32d0a88b3907e4b0dc36809fda477f0757c59a505d4e9b455f384b8b"}, - {file = "pydantic_core-2.18.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25595ac311f20e5324d1941909b0d12933f1fd2171075fcff763e90f43e92a0d"}, - {file = "pydantic_core-2.18.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14fe73881cf8e4cbdaded8ca0aa671635b597e42447fec7060d0868b52d074e6"}, - {file = "pydantic_core-2.18.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca976884ce34070799e4dfc6fbd68cb1d181db1eefe4a3a94798ddfb34b8867f"}, - {file = "pydantic_core-2.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:684d840d2c9ec5de9cb397fcb3f36d5ebb6fa0d94734f9886032dd796c1ead06"}, - {file = "pydantic_core-2.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:54764c083bbe0264f0f746cefcded6cb08fbbaaf1ad1d78fb8a4c30cff999a90"}, - {file = "pydantic_core-2.18.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:201713f2f462e5c015b343e86e68bd8a530a4f76609b33d8f0ec65d2b921712a"}, - {file = "pydantic_core-2.18.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fd1a9edb9dd9d79fbeac1ea1f9a8dd527a6113b18d2e9bcc0d541d308dae639b"}, - {file = "pydantic_core-2.18.1-cp312-none-win32.whl", hash = "sha256:d5e6b7155b8197b329dc787356cfd2684c9d6a6b1a197f6bbf45f5555a98d411"}, - {file = "pydantic_core-2.18.1-cp312-none-win_amd64.whl", hash = "sha256:9376d83d686ec62e8b19c0ac3bf8d28d8a5981d0df290196fb6ef24d8a26f0d6"}, - {file = "pydantic_core-2.18.1-cp312-none-win_arm64.whl", hash = "sha256:c562b49c96906b4029b5685075fe1ebd3b5cc2601dfa0b9e16c2c09d6cbce048"}, - {file = "pydantic_core-2.18.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:3e352f0191d99fe617371096845070dee295444979efb8f27ad941227de6ad09"}, - {file = "pydantic_core-2.18.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0295d52b012cbe0d3059b1dba99159c3be55e632aae1999ab74ae2bd86a33d7"}, - {file = "pydantic_core-2.18.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56823a92075780582d1ffd4489a2e61d56fd3ebb4b40b713d63f96dd92d28144"}, - {file = "pydantic_core-2.18.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dd3f79e17b56741b5177bcc36307750d50ea0698df6aa82f69c7db32d968c1c2"}, - {file = "pydantic_core-2.18.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38a5024de321d672a132b1834a66eeb7931959c59964b777e8f32dbe9523f6b1"}, - {file = "pydantic_core-2.18.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2ce426ee691319d4767748c8e0895cfc56593d725594e415f274059bcf3cb76"}, - {file = "pydantic_core-2.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2adaeea59849ec0939af5c5d476935f2bab4b7f0335b0110f0f069a41024278e"}, - {file = "pydantic_core-2.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9b6431559676a1079eac0f52d6d0721fb8e3c5ba43c37bc537c8c83724031feb"}, - {file = "pydantic_core-2.18.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:85233abb44bc18d16e72dc05bf13848a36f363f83757541f1a97db2f8d58cfd9"}, - {file = "pydantic_core-2.18.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:641a018af4fe48be57a2b3d7a1f0f5dbca07c1d00951d3d7463f0ac9dac66622"}, - {file = "pydantic_core-2.18.1-cp38-none-win32.whl", hash = "sha256:63d7523cd95d2fde0d28dc42968ac731b5bb1e516cc56b93a50ab293f4daeaad"}, - {file = "pydantic_core-2.18.1-cp38-none-win_amd64.whl", hash = "sha256:907a4d7720abfcb1c81619863efd47c8a85d26a257a2dbebdb87c3b847df0278"}, - {file = "pydantic_core-2.18.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:aad17e462f42ddbef5984d70c40bfc4146c322a2da79715932cd8976317054de"}, - {file = "pydantic_core-2.18.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:94b9769ba435b598b547c762184bcfc4783d0d4c7771b04a3b45775c3589ca44"}, - {file = "pydantic_core-2.18.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80e0e57cc704a52fb1b48f16d5b2c8818da087dbee6f98d9bf19546930dc64b5"}, - {file = "pydantic_core-2.18.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:76b86e24039c35280ceee6dce7e62945eb93a5175d43689ba98360ab31eebc4a"}, - {file = "pydantic_core-2.18.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12a05db5013ec0ca4a32cc6433f53faa2a014ec364031408540ba858c2172bb0"}, - {file = "pydantic_core-2.18.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:250ae39445cb5475e483a36b1061af1bc233de3e9ad0f4f76a71b66231b07f88"}, - {file = "pydantic_core-2.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a32204489259786a923e02990249c65b0f17235073149d0033efcebe80095570"}, - {file = "pydantic_core-2.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6395a4435fa26519fd96fdccb77e9d00ddae9dd6c742309bd0b5610609ad7fb2"}, - {file = "pydantic_core-2.18.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2533ad2883f001efa72f3d0e733fb846710c3af6dcdd544fe5bf14fa5fe2d7db"}, - {file = "pydantic_core-2.18.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b560b72ed4816aee52783c66854d96157fd8175631f01ef58e894cc57c84f0f6"}, - {file = "pydantic_core-2.18.1-cp39-none-win32.whl", hash = "sha256:582cf2cead97c9e382a7f4d3b744cf0ef1a6e815e44d3aa81af3ad98762f5a9b"}, - {file = "pydantic_core-2.18.1-cp39-none-win_amd64.whl", hash = "sha256:ca71d501629d1fa50ea7fa3b08ba884fe10cefc559f5c6c8dfe9036c16e8ae89"}, - {file = "pydantic_core-2.18.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e178e5b66a06ec5bf51668ec0d4ac8cfb2bdcb553b2c207d58148340efd00143"}, - {file = "pydantic_core-2.18.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:72722ce529a76a4637a60be18bd789d8fb871e84472490ed7ddff62d5fed620d"}, - {file = "pydantic_core-2.18.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fe0c1ce5b129455e43f941f7a46f61f3d3861e571f2905d55cdbb8b5c6f5e2c"}, - {file = "pydantic_core-2.18.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4284c621f06a72ce2cb55f74ea3150113d926a6eb78ab38340c08f770eb9b4d"}, - {file = "pydantic_core-2.18.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a0c3e718f4e064efde68092d9d974e39572c14e56726ecfaeebbe6544521f47"}, - {file = "pydantic_core-2.18.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:2027493cc44c23b598cfaf200936110433d9caa84e2c6cf487a83999638a96ac"}, - {file = "pydantic_core-2.18.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:76909849d1a6bffa5a07742294f3fa1d357dc917cb1fe7b470afbc3a7579d539"}, - {file = "pydantic_core-2.18.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ee7ccc7fb7e921d767f853b47814c3048c7de536663e82fbc37f5eb0d532224b"}, - {file = "pydantic_core-2.18.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ee2794111c188548a4547eccc73a6a8527fe2af6cf25e1a4ebda2fd01cdd2e60"}, - {file = "pydantic_core-2.18.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a139fe9f298dc097349fb4f28c8b81cc7a202dbfba66af0e14be5cfca4ef7ce5"}, - {file = "pydantic_core-2.18.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d074b07a10c391fc5bbdcb37b2f16f20fcd9e51e10d01652ab298c0d07908ee2"}, - {file = "pydantic_core-2.18.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c69567ddbac186e8c0aadc1f324a60a564cfe25e43ef2ce81bcc4b8c3abffbae"}, - {file = "pydantic_core-2.18.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:baf1c7b78cddb5af00971ad5294a4583188bda1495b13760d9f03c9483bb6203"}, - {file = "pydantic_core-2.18.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:2684a94fdfd1b146ff10689c6e4e815f6a01141781c493b97342cdc5b06f4d5d"}, - {file = "pydantic_core-2.18.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:73c1bc8a86a5c9e8721a088df234265317692d0b5cd9e86e975ce3bc3db62a59"}, - {file = "pydantic_core-2.18.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e60defc3c15defb70bb38dd605ff7e0fae5f6c9c7cbfe0ad7868582cb7e844a6"}, - {file = "pydantic_core-2.18.1.tar.gz", hash = "sha256:de9d3e8717560eb05e28739d1b35e4eac2e458553a52a301e51352a7ffc86a35"}, + {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"}, + {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"}, + {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"}, + {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"}, + {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"}, + {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"}, + {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"}, + {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"}, + {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"}, + {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"}, + {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"}, + {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"}, + {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"}, + {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"}, + {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"}, + {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"}, + {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"}, + {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"}, + {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"}, + {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"}, + {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"}, + {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"}, + {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"}, + {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"}, + {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"}, + {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"}, + {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"}, + {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"}, + {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"}, + {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"}, + {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"}, + {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"}, + {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"}, + {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"}, + {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"}, + {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"}, + {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"}, ] [package.dependencies] @@ -5212,13 +5574,13 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pydantic-settings" -version = "2.3.1" +version = "2.3.4" description = "Settings management using Pydantic" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_settings-2.3.1-py3-none-any.whl", hash = "sha256:acb2c213140dfff9669f4fe9f8180d43914f51626db28ab2db7308a576cce51a"}, - {file = "pydantic_settings-2.3.1.tar.gz", hash = "sha256:e34bbd649803a6bb3e2f0f58fb0edff1f0c7f556849fda106cc21bcce12c30ab"}, + {file = "pydantic_settings-2.3.4-py3-none-any.whl", hash = "sha256:11ad8bacb68a045f00e4f862c7a718c8a9ec766aa8fd4c32e39a0594b207b53a"}, + {file = "pydantic_settings-2.3.4.tar.gz", hash = "sha256:c5802e3d62b78e82522319bbc9b8f8ffb28ad1c988a99311d04f2a6051fca0a7"}, ] [package.dependencies] @@ -5271,13 +5633,13 @@ torch = ["torch"] [[package]] name = "pylint" -version = "3.2.3" +version = "3.2.5" description = "python code static checker" optional = false python-versions = ">=3.8.0" files = [ - {file = "pylint-3.2.3-py3-none-any.whl", hash = "sha256:b3d7d2708a3e04b4679e02d99e72329a8b7ee8afb8d04110682278781f889fa8"}, - {file = "pylint-3.2.3.tar.gz", hash = "sha256:02f6c562b215582386068d52a30f520d84fdbcf2a95fc7e855b816060d048b60"}, + {file = "pylint-3.2.5-py3-none-any.whl", hash = "sha256:32cd6c042b5004b8e857d727708720c54a676d1e22917cf1a2df9b4d4868abd6"}, + {file = "pylint-3.2.5.tar.gz", hash = "sha256:e9b7171e242dcc6ebd0aaa7540481d1a72860748a0a7816b8fe6cf6c80a6fe7e"}, ] [package.dependencies] @@ -5332,13 +5694,13 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pypdf" -version = "4.2.0" +version = "4.3.0" description = "A pure-python PDF library capable of splitting, merging, cropping, and transforming PDF files" optional = false python-versions = ">=3.6" files = [ - {file = "pypdf-4.2.0-py3-none-any.whl", hash = "sha256:dc035581664e0ad717e3492acebc1a5fc23dba759e788e3d4a9fc9b1a32e72c1"}, - {file = "pypdf-4.2.0.tar.gz", hash = "sha256:fe63f3f7d1dcda1c9374421a94c1bba6c6f8c4a62173a59b64ffd52058f846b1"}, + {file = "pypdf-4.3.0-py3-none-any.whl", hash = "sha256:eeea4d019b57c099d02a0e1692eaaab23341ae3f255c1dafa3c8566b4636496d"}, + {file = "pypdf-4.3.0.tar.gz", hash = "sha256:0d7a4c67fd03782f5a09d3f48c11c7a31e0bb9af78861a25229bb49259ed0504"}, ] [package.dependencies] @@ -5351,6 +5713,28 @@ docs = ["myst_parser", "sphinx", "sphinx_rtd_theme"] full = ["Pillow (>=8.0.0)", "PyCryptodome", "cryptography"] image = ["Pillow (>=8.0.0)"] +[[package]] +name = "pypdfium2" +version = "4.30.0" +description = "Python bindings to PDFium" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pypdfium2-4.30.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:b33ceded0b6ff5b2b93bc1fe0ad4b71aa6b7e7bd5875f1ca0cdfb6ba6ac01aab"}, + {file = "pypdfium2-4.30.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4e55689f4b06e2d2406203e771f78789bd4f190731b5d57383d05cf611d829de"}, + {file = "pypdfium2-4.30.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e6e50f5ce7f65a40a33d7c9edc39f23140c57e37144c2d6d9e9262a2a854854"}, + {file = "pypdfium2-4.30.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3d0dd3ecaffd0b6dbda3da663220e705cb563918249bda26058c6036752ba3a2"}, + {file = "pypdfium2-4.30.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc3bf29b0db8c76cdfaac1ec1cde8edf211a7de7390fbf8934ad2aa9b4d6dfad"}, + {file = "pypdfium2-4.30.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1f78d2189e0ddf9ac2b7a9b9bd4f0c66f54d1389ff6c17e9fd9dc034d06eb3f"}, + {file = "pypdfium2-4.30.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:5eda3641a2da7a7a0b2f4dbd71d706401a656fea521b6b6faa0675b15d31a163"}, + {file = "pypdfium2-4.30.0-py3-none-musllinux_1_1_i686.whl", hash = "sha256:0dfa61421b5eb68e1188b0b2231e7ba35735aef2d867d86e48ee6cab6975195e"}, + {file = "pypdfium2-4.30.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:f33bd79e7a09d5f7acca3b0b69ff6c8a488869a7fab48fdf400fec6e20b9c8be"}, + {file = "pypdfium2-4.30.0-py3-none-win32.whl", hash = "sha256:ee2410f15d576d976c2ab2558c93d392a25fb9f6635e8dd0a8a3a5241b275e0e"}, + {file = "pypdfium2-4.30.0-py3-none-win_amd64.whl", hash = "sha256:90dbb2ac07be53219f56be09961eb95cf2473f834d01a42d901d13ccfad64b4c"}, + {file = "pypdfium2-4.30.0-py3-none-win_arm64.whl", hash = "sha256:119b2969a6d6b1e8d55e99caaf05290294f2d0fe49c12a3f17102d01c441bd29"}, + {file = "pypdfium2-4.30.0.tar.gz", hash = "sha256:48b5b7e5566665bc1015b9d69c1ebabe21f6aee468b509531c3c8318eeee2e16"}, +] + [[package]] name = "pyreadline3" version = "3.4.1" @@ -5545,7 +5929,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -5696,13 +6079,13 @@ cffi = {version = "*", markers = "implementation_name == \"pypy\""} [[package]] name = "qdrant-client" -version = "1.9.1" +version = "1.10.1" description = "Client library for the Qdrant vector search engine" optional = false python-versions = ">=3.8" files = [ - {file = "qdrant_client-1.9.1-py3-none-any.whl", hash = "sha256:b9b7e0e5c1a51410d8bb5106a869a51e12f92ab45a99030f27aba790553bd2c8"}, - {file = "qdrant_client-1.9.1.tar.gz", hash = "sha256:186b9c31d95aefe8f2db84b7746402d7365bd63b305550e530e31bde2002ce79"}, + {file = "qdrant_client-1.10.1-py3-none-any.whl", hash = "sha256:b9fb8fe50dd168d92b2998be7c6135d5a229b3a3258ad158cc69c8adf9ff1810"}, + {file = "qdrant_client-1.10.1.tar.gz", hash = "sha256:2284c8c5bb1defb0d9dbacb07d16f344972f395f4f2ed062318476a7951fd84c"}, ] [package.dependencies] @@ -5715,7 +6098,8 @@ pydantic = ">=1.10.8" urllib3 = ">=1.26.14,<3" [package.extras] -fastembed = ["fastembed (==0.2.6)"] +fastembed = ["fastembed (==0.2.7)"] +fastembed-gpu = ["fastembed-gpu (==0.2.7)"] [[package]] name = "ratelimiter" @@ -5929,110 +6313,110 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "rpds-py" -version = "0.18.1" +version = "0.19.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.18.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:d31dea506d718693b6b2cffc0648a8929bdc51c70a311b2770f09611caa10d53"}, - {file = "rpds_py-0.18.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:732672fbc449bab754e0b15356c077cc31566df874964d4801ab14f71951ea80"}, - {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a98a1f0552b5f227a3d6422dbd61bc6f30db170939bd87ed14f3c339aa6c7c9"}, - {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f1944ce16401aad1e3f7d312247b3d5de7981f634dc9dfe90da72b87d37887d"}, - {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38e14fb4e370885c4ecd734f093a2225ee52dc384b86fa55fe3f74638b2cfb09"}, - {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08d74b184f9ab6289b87b19fe6a6d1a97fbfea84b8a3e745e87a5de3029bf944"}, - {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d70129cef4a8d979caa37e7fe957202e7eee8ea02c5e16455bc9808a59c6b2f0"}, - {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce0bb20e3a11bd04461324a6a798af34d503f8d6f1aa3d2aa8901ceaf039176d"}, - {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81c5196a790032e0fc2464c0b4ab95f8610f96f1f2fa3d4deacce6a79852da60"}, - {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f3027be483868c99b4985fda802a57a67fdf30c5d9a50338d9db646d590198da"}, - {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d44607f98caa2961bab4fa3c4309724b185b464cdc3ba6f3d7340bac3ec97cc1"}, - {file = "rpds_py-0.18.1-cp310-none-win32.whl", hash = "sha256:c273e795e7a0f1fddd46e1e3cb8be15634c29ae8ff31c196debb620e1edb9333"}, - {file = "rpds_py-0.18.1-cp310-none-win_amd64.whl", hash = "sha256:8352f48d511de5f973e4f2f9412736d7dea76c69faa6d36bcf885b50c758ab9a"}, - {file = "rpds_py-0.18.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6b5ff7e1d63a8281654b5e2896d7f08799378e594f09cf3674e832ecaf396ce8"}, - {file = "rpds_py-0.18.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8927638a4d4137a289e41d0fd631551e89fa346d6dbcfc31ad627557d03ceb6d"}, - {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:154bf5c93d79558b44e5b50cc354aa0459e518e83677791e6adb0b039b7aa6a7"}, - {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07f2139741e5deb2c5154a7b9629bc5aa48c766b643c1a6750d16f865a82c5fc"}, - {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c7672e9fba7425f79019db9945b16e308ed8bc89348c23d955c8c0540da0a07"}, - {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:489bdfe1abd0406eba6b3bb4fdc87c7fa40f1031de073d0cfb744634cc8fa261"}, - {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c20f05e8e3d4fc76875fc9cb8cf24b90a63f5a1b4c5b9273f0e8225e169b100"}, - {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:967342e045564cef76dfcf1edb700b1e20838d83b1aa02ab313e6a497cf923b8"}, - {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2cc7c1a47f3a63282ab0f422d90ddac4aa3034e39fc66a559ab93041e6505da7"}, - {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f7afbfee1157e0f9376c00bb232e80a60e59ed716e3211a80cb8506550671e6e"}, - {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e6934d70dc50f9f8ea47081ceafdec09245fd9f6032669c3b45705dea096b88"}, - {file = "rpds_py-0.18.1-cp311-none-win32.whl", hash = "sha256:c69882964516dc143083d3795cb508e806b09fc3800fd0d4cddc1df6c36e76bb"}, - {file = "rpds_py-0.18.1-cp311-none-win_amd64.whl", hash = "sha256:70a838f7754483bcdc830444952fd89645569e7452e3226de4a613a4c1793fb2"}, - {file = "rpds_py-0.18.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3dd3cd86e1db5aadd334e011eba4e29d37a104b403e8ca24dcd6703c68ca55b3"}, - {file = "rpds_py-0.18.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:05f3d615099bd9b13ecf2fc9cf2d839ad3f20239c678f461c753e93755d629ee"}, - {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35b2b771b13eee8729a5049c976197ff58a27a3829c018a04341bcf1ae409b2b"}, - {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ee17cd26b97d537af8f33635ef38be873073d516fd425e80559f4585a7b90c43"}, - {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b646bf655b135ccf4522ed43d6902af37d3f5dbcf0da66c769a2b3938b9d8184"}, - {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19ba472b9606c36716062c023afa2484d1e4220548751bda14f725a7de17b4f6"}, - {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e30ac5e329098903262dc5bdd7e2086e0256aa762cc8b744f9e7bf2a427d3f8"}, - {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d58ad6317d188c43750cb76e9deacf6051d0f884d87dc6518e0280438648a9ac"}, - {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e1735502458621921cee039c47318cb90b51d532c2766593be6207eec53e5c4c"}, - {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f5bab211605d91db0e2995a17b5c6ee5edec1270e46223e513eaa20da20076ac"}, - {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2fc24a329a717f9e2448f8cd1f960f9dac4e45b6224d60734edeb67499bab03a"}, - {file = "rpds_py-0.18.1-cp312-none-win32.whl", hash = "sha256:1805d5901779662d599d0e2e4159d8a82c0b05faa86ef9222bf974572286b2b6"}, - {file = "rpds_py-0.18.1-cp312-none-win_amd64.whl", hash = "sha256:720edcb916df872d80f80a1cc5ea9058300b97721efda8651efcd938a9c70a72"}, - {file = "rpds_py-0.18.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:c827576e2fa017a081346dce87d532a5310241648eb3700af9a571a6e9fc7e74"}, - {file = "rpds_py-0.18.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aa3679e751408d75a0b4d8d26d6647b6d9326f5e35c00a7ccd82b78ef64f65f8"}, - {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0abeee75434e2ee2d142d650d1e54ac1f8b01e6e6abdde8ffd6eeac6e9c38e20"}, - {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed402d6153c5d519a0faf1bb69898e97fb31613b49da27a84a13935ea9164dfc"}, - {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:338dee44b0cef8b70fd2ef54b4e09bb1b97fc6c3a58fea5db6cc083fd9fc2724"}, - {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7750569d9526199c5b97e5a9f8d96a13300950d910cf04a861d96f4273d5b104"}, - {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:607345bd5912aacc0c5a63d45a1f73fef29e697884f7e861094e443187c02be5"}, - {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:207c82978115baa1fd8d706d720b4a4d2b0913df1c78c85ba73fe6c5804505f0"}, - {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6d1e42d2735d437e7e80bab4d78eb2e459af48c0a46e686ea35f690b93db792d"}, - {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5463c47c08630007dc0fe99fb480ea4f34a89712410592380425a9b4e1611d8e"}, - {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:06d218939e1bf2ca50e6b0ec700ffe755e5216a8230ab3e87c059ebb4ea06afc"}, - {file = "rpds_py-0.18.1-cp38-none-win32.whl", hash = "sha256:312fe69b4fe1ffbe76520a7676b1e5ac06ddf7826d764cc10265c3b53f96dbe9"}, - {file = "rpds_py-0.18.1-cp38-none-win_amd64.whl", hash = "sha256:9437ca26784120a279f3137ee080b0e717012c42921eb07861b412340f85bae2"}, - {file = "rpds_py-0.18.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:19e515b78c3fc1039dd7da0a33c28c3154458f947f4dc198d3c72db2b6b5dc93"}, - {file = "rpds_py-0.18.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7b28c5b066bca9a4eb4e2f2663012debe680f097979d880657f00e1c30875a0"}, - {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:673fdbbf668dd958eff750e500495ef3f611e2ecc209464f661bc82e9838991e"}, - {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d960de62227635d2e61068f42a6cb6aae91a7fe00fca0e3aeed17667c8a34611"}, - {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:352a88dc7892f1da66b6027af06a2e7e5d53fe05924cc2cfc56495b586a10b72"}, - {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e0ee01ad8260184db21468a6e1c37afa0529acc12c3a697ee498d3c2c4dcaf3"}, - {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4c39ad2f512b4041343ea3c7894339e4ca7839ac38ca83d68a832fc8b3748ab"}, - {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aaa71ee43a703c321906813bb252f69524f02aa05bf4eec85f0c41d5d62d0f4c"}, - {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6cd8098517c64a85e790657e7b1e509b9fe07487fd358e19431cb120f7d96338"}, - {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4adec039b8e2928983f885c53b7cc4cda8965b62b6596501a0308d2703f8af1b"}, - {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:32b7daaa3e9389db3695964ce8e566e3413b0c43e3394c05e4b243a4cd7bef26"}, - {file = "rpds_py-0.18.1-cp39-none-win32.whl", hash = "sha256:2625f03b105328729f9450c8badda34d5243231eef6535f80064d57035738360"}, - {file = "rpds_py-0.18.1-cp39-none-win_amd64.whl", hash = "sha256:bf18932d0003c8c4d51a39f244231986ab23ee057d235a12b2684ea26a353590"}, - {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cbfbea39ba64f5e53ae2915de36f130588bba71245b418060ec3330ebf85678e"}, - {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a3d456ff2a6a4d2adcdf3c1c960a36f4fd2fec6e3b4902a42a384d17cf4e7a65"}, - {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7700936ef9d006b7ef605dc53aa364da2de5a3aa65516a1f3ce73bf82ecfc7ae"}, - {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:51584acc5916212e1bf45edd17f3a6b05fe0cbb40482d25e619f824dccb679de"}, - {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:942695a206a58d2575033ff1e42b12b2aece98d6003c6bc739fbf33d1773b12f"}, - {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b906b5f58892813e5ba5c6056d6a5ad08f358ba49f046d910ad992196ea61397"}, - {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f8e3fecca256fefc91bb6765a693d96692459d7d4c644660a9fff32e517843"}, - {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7732770412bab81c5a9f6d20aeb60ae943a9b36dcd990d876a773526468e7163"}, - {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:bd1105b50ede37461c1d51b9698c4f4be6e13e69a908ab7751e3807985fc0346"}, - {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:618916f5535784960f3ecf8111581f4ad31d347c3de66d02e728de460a46303c"}, - {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:17c6d2155e2423f7e79e3bb18151c686d40db42d8645e7977442170c360194d4"}, - {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c4c4c3f878df21faf5fac86eda32671c27889e13570645a9eea0a1abdd50922"}, - {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:fab6ce90574645a0d6c58890e9bcaac8d94dff54fb51c69e5522a7358b80ab64"}, - {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:531796fb842b53f2695e94dc338929e9f9dbf473b64710c28af5a160b2a8927d"}, - {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:740884bc62a5e2bbb31e584f5d23b32320fd75d79f916f15a788d527a5e83644"}, - {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:998125738de0158f088aef3cb264a34251908dd2e5d9966774fdab7402edfab7"}, - {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e2be6e9dd4111d5b31ba3b74d17da54a8319d8168890fbaea4b9e5c3de630ae5"}, - {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0cee71bc618cd93716f3c1bf56653740d2d13ddbd47673efa8bf41435a60daa"}, - {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c3caec4ec5cd1d18e5dd6ae5194d24ed12785212a90b37f5f7f06b8bedd7139"}, - {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:27bba383e8c5231cd559affe169ca0b96ec78d39909ffd817f28b166d7ddd4d8"}, - {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:a888e8bdb45916234b99da2d859566f1e8a1d2275a801bb8e4a9644e3c7e7909"}, - {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6031b25fb1b06327b43d841f33842b383beba399884f8228a6bb3df3088485ff"}, - {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48c2faaa8adfacefcbfdb5f2e2e7bdad081e5ace8d182e5f4ade971f128e6bb3"}, - {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d85164315bd68c0806768dc6bb0429c6f95c354f87485ee3593c4f6b14def2bd"}, - {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6afd80f6c79893cfc0574956f78a0add8c76e3696f2d6a15bca2c66c415cf2d4"}, - {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa242ac1ff583e4ec7771141606aafc92b361cd90a05c30d93e343a0c2d82a89"}, - {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21be4770ff4e08698e1e8e0bce06edb6ea0626e7c8f560bc08222880aca6a6f"}, - {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c45a639e93a0c5d4b788b2613bd637468edd62f8f95ebc6fcc303d58ab3f0a8"}, - {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910e71711d1055b2768181efa0a17537b2622afeb0424116619817007f8a2b10"}, - {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9bb1f182a97880f6078283b3505a707057c42bf55d8fca604f70dedfdc0772a"}, - {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d54f74f40b1f7aaa595a02ff42ef38ca654b1469bef7d52867da474243cc633"}, - {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:8d2e182c9ee01135e11e9676e9a62dfad791a7a467738f06726872374a83db49"}, - {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:636a15acc588f70fda1661234761f9ed9ad79ebed3f2125d44be0862708b666e"}, - {file = "rpds_py-0.18.1.tar.gz", hash = "sha256:dc48b479d540770c811fbd1eb9ba2bb66951863e448efec2e2c102625328e92f"}, + {file = "rpds_py-0.19.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:fb37bd599f031f1a6fb9e58ec62864ccf3ad549cf14bac527dbfa97123edcca4"}, + {file = "rpds_py-0.19.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3384d278df99ec2c6acf701d067147320b864ef6727405d6470838476e44d9e8"}, + {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e54548e0be3ac117595408fd4ca0ac9278fde89829b0b518be92863b17ff67a2"}, + {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8eb488ef928cdbc05a27245e52de73c0d7c72a34240ef4d9893fdf65a8c1a955"}, + {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5da93debdfe27b2bfc69eefb592e1831d957b9535e0943a0ee8b97996de21b5"}, + {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:79e205c70afddd41f6ee79a8656aec738492a550247a7af697d5bd1aee14f766"}, + {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:959179efb3e4a27610e8d54d667c02a9feaa86bbabaf63efa7faa4dfa780d4f1"}, + {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a6e605bb9edcf010f54f8b6a590dd23a4b40a8cb141255eec2a03db249bc915b"}, + {file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9133d75dc119a61d1a0ded38fb9ba40a00ef41697cc07adb6ae098c875195a3f"}, + {file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd36b712d35e757e28bf2f40a71e8f8a2d43c8b026d881aa0c617b450d6865c9"}, + {file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:354f3a91718489912f2e0fc331c24eaaf6a4565c080e00fbedb6015857c00582"}, + {file = "rpds_py-0.19.0-cp310-none-win32.whl", hash = "sha256:ebcbf356bf5c51afc3290e491d3722b26aaf5b6af3c1c7f6a1b757828a46e336"}, + {file = "rpds_py-0.19.0-cp310-none-win_amd64.whl", hash = "sha256:75a6076289b2df6c8ecb9d13ff79ae0cad1d5fb40af377a5021016d58cd691ec"}, + {file = "rpds_py-0.19.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6d45080095e585f8c5097897313def60caa2046da202cdb17a01f147fb263b81"}, + {file = "rpds_py-0.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5c9581019c96f865483d031691a5ff1cc455feb4d84fc6920a5ffc48a794d8a"}, + {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1540d807364c84516417115c38f0119dfec5ea5c0dd9a25332dea60b1d26fc4d"}, + {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9e65489222b410f79711dc3d2d5003d2757e30874096b2008d50329ea4d0f88c"}, + {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9da6f400eeb8c36f72ef6646ea530d6d175a4f77ff2ed8dfd6352842274c1d8b"}, + {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:37f46bb11858717e0efa7893c0f7055c43b44c103e40e69442db5061cb26ed34"}, + {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:071d4adc734de562bd11d43bd134330fb6249769b2f66b9310dab7460f4bf714"}, + {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9625367c8955e4319049113ea4f8fee0c6c1145192d57946c6ffcd8fe8bf48dd"}, + {file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e19509145275d46bc4d1e16af0b57a12d227c8253655a46bbd5ec317e941279d"}, + {file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d438e4c020d8c39961deaf58f6913b1bf8832d9b6f62ec35bd93e97807e9cbc"}, + {file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90bf55d9d139e5d127193170f38c584ed3c79e16638890d2e36f23aa1630b952"}, + {file = "rpds_py-0.19.0-cp311-none-win32.whl", hash = "sha256:8d6ad132b1bc13d05ffe5b85e7a01a3998bf3a6302ba594b28d61b8c2cf13aaf"}, + {file = "rpds_py-0.19.0-cp311-none-win_amd64.whl", hash = "sha256:7ec72df7354e6b7f6eb2a17fa6901350018c3a9ad78e48d7b2b54d0412539a67"}, + {file = "rpds_py-0.19.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:5095a7c838a8647c32aa37c3a460d2c48debff7fc26e1136aee60100a8cd8f68"}, + {file = "rpds_py-0.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f2f78ef14077e08856e788fa482107aa602636c16c25bdf59c22ea525a785e9"}, + {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7cc6cb44f8636fbf4a934ca72f3e786ba3c9f9ba4f4d74611e7da80684e48d2"}, + {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf902878b4af334a09de7a45badbff0389e7cf8dc2e4dcf5f07125d0b7c2656d"}, + {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:688aa6b8aa724db1596514751ffb767766e02e5c4a87486ab36b8e1ebc1aedac"}, + {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57dbc9167d48e355e2569346b5aa4077f29bf86389c924df25c0a8b9124461fb"}, + {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b4cf5a9497874822341c2ebe0d5850fed392034caadc0bad134ab6822c0925b"}, + {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8a790d235b9d39c70a466200d506bb33a98e2ee374a9b4eec7a8ac64c2c261fa"}, + {file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1d16089dfa58719c98a1c06f2daceba6d8e3fb9b5d7931af4a990a3c486241cb"}, + {file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bc9128e74fe94650367fe23f37074f121b9f796cabbd2f928f13e9661837296d"}, + {file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c8f77e661ffd96ff104bebf7d0f3255b02aa5d5b28326f5408d6284c4a8b3248"}, + {file = "rpds_py-0.19.0-cp312-none-win32.whl", hash = "sha256:5f83689a38e76969327e9b682be5521d87a0c9e5a2e187d2bc6be4765f0d4600"}, + {file = "rpds_py-0.19.0-cp312-none-win_amd64.whl", hash = "sha256:06925c50f86da0596b9c3c64c3837b2481337b83ef3519e5db2701df695453a4"}, + {file = "rpds_py-0.19.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:52e466bea6f8f3a44b1234570244b1cff45150f59a4acae3fcc5fd700c2993ca"}, + {file = "rpds_py-0.19.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e21cc693045fda7f745c790cb687958161ce172ffe3c5719ca1764e752237d16"}, + {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b31f059878eb1f5da8b2fd82480cc18bed8dcd7fb8fe68370e2e6285fa86da6"}, + {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1dd46f309e953927dd018567d6a9e2fb84783963650171f6c5fe7e5c41fd5666"}, + {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34a01a4490e170376cd79258b7f755fa13b1a6c3667e872c8e35051ae857a92b"}, + {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bcf426a8c38eb57f7bf28932e68425ba86def6e756a5b8cb4731d8e62e4e0223"}, + {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f68eea5df6347d3f1378ce992d86b2af16ad7ff4dcb4a19ccdc23dea901b87fb"}, + {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dab8d921b55a28287733263c0e4c7db11b3ee22aee158a4de09f13c93283c62d"}, + {file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6fe87efd7f47266dfc42fe76dae89060038f1d9cb911f89ae7e5084148d1cc08"}, + {file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:535d4b52524a961d220875688159277f0e9eeeda0ac45e766092bfb54437543f"}, + {file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:8b1a94b8afc154fbe36978a511a1f155f9bd97664e4f1f7a374d72e180ceb0ae"}, + {file = "rpds_py-0.19.0-cp38-none-win32.whl", hash = "sha256:7c98298a15d6b90c8f6e3caa6457f4f022423caa5fa1a1ca7a5e9e512bdb77a4"}, + {file = "rpds_py-0.19.0-cp38-none-win_amd64.whl", hash = "sha256:b0da31853ab6e58a11db3205729133ce0df26e6804e93079dee095be3d681dc1"}, + {file = "rpds_py-0.19.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5039e3cef7b3e7a060de468a4a60a60a1f31786da94c6cb054e7a3c75906111c"}, + {file = "rpds_py-0.19.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab1932ca6cb8c7499a4d87cb21ccc0d3326f172cfb6a64021a889b591bb3045c"}, + {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2afd2164a1e85226fcb6a1da77a5c8896c18bfe08e82e8ceced5181c42d2179"}, + {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b1c30841f5040de47a0046c243fc1b44ddc87d1b12435a43b8edff7e7cb1e0d0"}, + {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f757f359f30ec7dcebca662a6bd46d1098f8b9fb1fcd661a9e13f2e8ce343ba1"}, + {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15e65395a59d2e0e96caf8ee5389ffb4604e980479c32742936ddd7ade914b22"}, + {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb0f6eb3a320f24b94d177e62f4074ff438f2ad9d27e75a46221904ef21a7b05"}, + {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b228e693a2559888790936e20f5f88b6e9f8162c681830eda303bad7517b4d5a"}, + {file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2575efaa5d949c9f4e2cdbe7d805d02122c16065bfb8d95c129372d65a291a0b"}, + {file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:5c872814b77a4e84afa293a1bee08c14daed1068b2bb1cc312edbf020bbbca2b"}, + {file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:850720e1b383df199b8433a20e02b25b72f0fded28bc03c5bd79e2ce7ef050be"}, + {file = "rpds_py-0.19.0-cp39-none-win32.whl", hash = "sha256:ce84a7efa5af9f54c0aa7692c45861c1667080814286cacb9958c07fc50294fb"}, + {file = "rpds_py-0.19.0-cp39-none-win_amd64.whl", hash = "sha256:1c26da90b8d06227d7769f34915913911222d24ce08c0ab2d60b354e2d9c7aff"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:75969cf900d7be665ccb1622a9aba225cf386bbc9c3bcfeeab9f62b5048f4a07"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8445f23f13339da640d1be8e44e5baf4af97e396882ebbf1692aecd67f67c479"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5a7c1062ef8aea3eda149f08120f10795835fc1c8bc6ad948fb9652a113ca55"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:462b0c18fbb48fdbf980914a02ee38c423a25fcc4cf40f66bacc95a2d2d73bc8"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3208f9aea18991ac7f2b39721e947bbd752a1abbe79ad90d9b6a84a74d44409b"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3444fe52b82f122d8a99bf66777aed6b858d392b12f4c317da19f8234db4533"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88cb4bac7185a9f0168d38c01d7a00addece9822a52870eee26b8d5b61409213"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6b130bd4163c93798a6b9bb96be64a7c43e1cec81126ffa7ffaa106e1fc5cef5"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a707b158b4410aefb6b054715545bbb21aaa5d5d0080217290131c49c2124a6e"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dc9ac4659456bde7c567107556ab065801622396b435a3ff213daef27b495388"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:81ea573aa46d3b6b3d890cd3c0ad82105985e6058a4baed03cf92518081eec8c"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f148c3f47f7f29a79c38cc5d020edcb5ca780020fab94dbc21f9af95c463581"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0906357f90784a66e89ae3eadc2654f36c580a7d65cf63e6a616e4aec3a81be"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f629ecc2db6a4736b5ba95a8347b0089240d69ad14ac364f557d52ad68cf94b0"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c6feacd1d178c30e5bc37184526e56740342fd2aa6371a28367bad7908d454fc"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae8b6068ee374fdfab63689be0963333aa83b0815ead5d8648389a8ded593378"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78d57546bad81e0da13263e4c9ce30e96dcbe720dbff5ada08d2600a3502e526"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b6683a37338818646af718c9ca2a07f89787551057fae57c4ec0446dc6224b"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e8481b946792415adc07410420d6fc65a352b45d347b78fec45d8f8f0d7496f0"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:bec35eb20792ea64c3c57891bc3ca0bedb2884fbac2c8249d9b731447ecde4fa"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:aa5476c3e3a402c37779e95f7b4048db2cb5b0ed0b9d006983965e93f40fe05a"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:19d02c45f2507b489fd4df7b827940f1420480b3e2e471e952af4d44a1ea8e34"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a3e2fd14c5d49ee1da322672375963f19f32b3d5953f0615b175ff7b9d38daed"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:93a91c2640645303e874eada51f4f33351b84b351a689d470f8108d0e0694210"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5b9fc03bf76a94065299d4a2ecd8dfbae4ae8e2e8098bbfa6ab6413ca267709"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a4b07cdf3f84310c08c1de2c12ddadbb7a77568bcb16e95489f9c81074322ed"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba0ed0dc6763d8bd6e5de5cf0d746d28e706a10b615ea382ac0ab17bb7388633"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:474bc83233abdcf2124ed3f66230a1c8435896046caa4b0b5ab6013c640803cc"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329c719d31362355a96b435f4653e3b4b061fcc9eba9f91dd40804ca637d914e"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef9101f3f7b59043a34f1dccbb385ca760467590951952d6701df0da9893ca0c"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:0121803b0f424ee2109d6e1f27db45b166ebaa4b32ff47d6aa225642636cd834"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:8344127403dea42f5970adccf6c5957a71a47f522171fafaf4c6ddb41b61703a"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:443cec402ddd650bb2b885113e1dcedb22b1175c6be223b14246a714b61cd521"}, + {file = "rpds_py-0.19.0.tar.gz", hash = "sha256:4fdc9afadbeb393b4bbbad75481e0ea78e4469f2e1d713a90811700830b553a9"}, ] [[package]] @@ -6063,13 +6447,13 @@ files = [ [[package]] name = "s3transfer" -version = "0.10.1" +version = "0.10.2" description = "An Amazon S3 Transfer Manager" optional = false -python-versions = ">= 3.8" +python-versions = ">=3.8" files = [ - {file = "s3transfer-0.10.1-py3-none-any.whl", hash = "sha256:ceb252b11bcf87080fb7850a224fb6e05c8a776bab8f2b64b7f25b969464839d"}, - {file = "s3transfer-0.10.1.tar.gz", hash = "sha256:5683916b4c724f799e600f41dd9e10a9ff19871bf87623cc8f491cb4f5fa0a19"}, + {file = "s3transfer-0.10.2-py3-none-any.whl", hash = "sha256:eca1c20de70a39daee580aef4986996620f365c4e0fda6a86100231d62f1bf69"}, + {file = "s3transfer-0.10.2.tar.gz", hash = "sha256:0711534e9356d3cc692fdde846b4a1e4b0cb6519971860796e6bc4c7aea00ef6"}, ] [package.dependencies] @@ -6202,32 +6586,32 @@ torch = ["safetensors[numpy]", "torch (>=1.10)"] [[package]] name = "scikit-learn" -version = "1.5.0" +version = "1.5.1" description = "A set of python modules for machine learning and data mining" optional = false python-versions = ">=3.9" files = [ - {file = "scikit_learn-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:12e40ac48555e6b551f0a0a5743cc94cc5a765c9513fe708e01f0aa001da2801"}, - {file = "scikit_learn-1.5.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f405c4dae288f5f6553b10c4ac9ea7754d5180ec11e296464adb5d6ac68b6ef5"}, - {file = "scikit_learn-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df8ccabbf583315f13160a4bb06037bde99ea7d8211a69787a6b7c5d4ebb6fc3"}, - {file = "scikit_learn-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c75ea812cd83b1385bbfa94ae971f0d80adb338a9523f6bbcb5e0b0381151d4"}, - {file = "scikit_learn-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:a90c5da84829a0b9b4bf00daf62754b2be741e66b5946911f5bdfaa869fcedd6"}, - {file = "scikit_learn-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2a65af2d8a6cce4e163a7951a4cfbfa7fceb2d5c013a4b593686c7f16445cf9d"}, - {file = "scikit_learn-1.5.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:4c0c56c3005f2ec1db3787aeaabefa96256580678cec783986836fc64f8ff622"}, - {file = "scikit_learn-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f77547165c00625551e5c250cefa3f03f2fc92c5e18668abd90bfc4be2e0bff"}, - {file = "scikit_learn-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:118a8d229a41158c9f90093e46b3737120a165181a1b58c03461447aa4657415"}, - {file = "scikit_learn-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:a03b09f9f7f09ffe8c5efffe2e9de1196c696d811be6798ad5eddf323c6f4d40"}, - {file = "scikit_learn-1.5.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:460806030c666addee1f074788b3978329a5bfdc9b7d63e7aad3f6d45c67a210"}, - {file = "scikit_learn-1.5.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:1b94d6440603752b27842eda97f6395f570941857456c606eb1d638efdb38184"}, - {file = "scikit_learn-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d82c2e573f0f2f2f0be897e7a31fcf4e73869247738ab8c3ce7245549af58ab8"}, - {file = "scikit_learn-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3a10e1d9e834e84d05e468ec501a356226338778769317ee0b84043c0d8fb06"}, - {file = "scikit_learn-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:855fc5fa8ed9e4f08291203af3d3e5fbdc4737bd617a371559aaa2088166046e"}, - {file = "scikit_learn-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:40fb7d4a9a2db07e6e0cae4dc7bdbb8fada17043bac24104d8165e10e4cff1a2"}, - {file = "scikit_learn-1.5.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:47132440050b1c5beb95f8ba0b2402bbd9057ce96ec0ba86f2f445dd4f34df67"}, - {file = "scikit_learn-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:174beb56e3e881c90424e21f576fa69c4ffcf5174632a79ab4461c4c960315ac"}, - {file = "scikit_learn-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261fe334ca48f09ed64b8fae13f9b46cc43ac5f580c4a605cbb0a517456c8f71"}, - {file = "scikit_learn-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:057b991ac64b3e75c9c04b5f9395eaf19a6179244c089afdebaad98264bff37c"}, - {file = "scikit_learn-1.5.0.tar.gz", hash = "sha256:789e3db01c750ed6d496fa2db7d50637857b451e57bcae863bff707c1247bef7"}, + {file = "scikit_learn-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:781586c414f8cc58e71da4f3d7af311e0505a683e112f2f62919e3019abd3745"}, + {file = "scikit_learn-1.5.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f5b213bc29cc30a89a3130393b0e39c847a15d769d6e59539cd86b75d276b1a7"}, + {file = "scikit_learn-1.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ff4ba34c2abff5ec59c803ed1d97d61b036f659a17f55be102679e88f926fac"}, + {file = "scikit_learn-1.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:161808750c267b77b4a9603cf9c93579c7a74ba8486b1336034c2f1579546d21"}, + {file = "scikit_learn-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:10e49170691514a94bb2e03787aa921b82dbc507a4ea1f20fd95557862c98dc1"}, + {file = "scikit_learn-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:154297ee43c0b83af12464adeab378dee2d0a700ccd03979e2b821e7dd7cc1c2"}, + {file = "scikit_learn-1.5.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:b5e865e9bd59396220de49cb4a57b17016256637c61b4c5cc81aaf16bc123bbe"}, + {file = "scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:909144d50f367a513cee6090873ae582dba019cb3fca063b38054fa42704c3a4"}, + {file = "scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:689b6f74b2c880276e365fe84fe4f1befd6a774f016339c65655eaff12e10cbf"}, + {file = "scikit_learn-1.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:9a07f90846313a7639af6a019d849ff72baadfa4c74c778821ae0fad07b7275b"}, + {file = "scikit_learn-1.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5944ce1faada31c55fb2ba20a5346b88e36811aab504ccafb9f0339e9f780395"}, + {file = "scikit_learn-1.5.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:0828673c5b520e879f2af6a9e99eee0eefea69a2188be1ca68a6121b809055c1"}, + {file = "scikit_learn-1.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:508907e5f81390e16d754e8815f7497e52139162fd69c4fdbd2dfa5d6cc88915"}, + {file = "scikit_learn-1.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97625f217c5c0c5d0505fa2af28ae424bd37949bb2f16ace3ff5f2f81fb4498b"}, + {file = "scikit_learn-1.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:da3f404e9e284d2b0a157e1b56b6566a34eb2798205cba35a211df3296ab7a74"}, + {file = "scikit_learn-1.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:88e0672c7ac21eb149d409c74cc29f1d611d5158175846e7a9c2427bd12b3956"}, + {file = "scikit_learn-1.5.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:7b073a27797a283187a4ef4ee149959defc350b46cbf63a84d8514fe16b69855"}, + {file = "scikit_learn-1.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b59e3e62d2be870e5c74af4e793293753565c7383ae82943b83383fdcf5cc5c1"}, + {file = "scikit_learn-1.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd8d3a19d4bd6dc5a7d4f358c8c3a60934dc058f363c34c0ac1e9e12a31421d"}, + {file = "scikit_learn-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:5f57428de0c900a98389c4a433d4a3cf89de979b3aa24d1c1d251802aa15e44d"}, + {file = "scikit_learn-1.5.1.tar.gz", hash = "sha256:0ea5d40c0e3951df445721927448755d3fe1d80833b0b7308ebff5d2a45e6414"}, ] [package.dependencies] @@ -6238,8 +6622,8 @@ threadpoolctl = ">=3.1.0" [package.extras] benchmark = ["matplotlib (>=3.3.4)", "memory_profiler (>=0.57.0)", "pandas (>=1.1.5)"] -build = ["cython (>=3.0.10)", "meson-python (>=0.15.0)", "numpy (>=1.19.5)", "scipy (>=1.6.0)"] -docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.3.4)", "memory_profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.1.5)", "plotly (>=5.14.0)", "polars (>=0.20.23)", "pooch (>=1.6.0)", "scikit-image (>=0.17.2)", "seaborn (>=0.9.0)", "sphinx (>=6.0.0)", "sphinx-copybutton (>=0.5.2)", "sphinx-gallery (>=0.15.0)", "sphinx-prompt (>=1.3.0)", "sphinxext-opengraph (>=0.4.2)"] +build = ["cython (>=3.0.10)", "meson-python (>=0.16.0)", "numpy (>=1.19.5)", "scipy (>=1.6.0)"] +docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.3.4)", "memory_profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.1.5)", "plotly (>=5.14.0)", "polars (>=0.20.23)", "pooch (>=1.6.0)", "pydata-sphinx-theme (>=0.15.3)", "scikit-image (>=0.17.2)", "seaborn (>=0.9.0)", "sphinx (>=7.3.7)", "sphinx-copybutton (>=0.5.2)", "sphinx-design (>=0.5.0)", "sphinx-gallery (>=0.16.0)", "sphinx-prompt (>=1.4.0)", "sphinx-remove-toctrees (>=1.0.0.post1)", "sphinxcontrib-sass (>=0.3.4)", "sphinxext-opengraph (>=0.9.1)"] examples = ["matplotlib (>=3.3.4)", "pandas (>=1.1.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.17.2)", "seaborn (>=0.9.0)"] install = ["joblib (>=1.2.0)", "numpy (>=1.19.5)", "scipy (>=1.6.0)", "threadpoolctl (>=3.1.0)"] maintenance = ["conda-lock (==2.5.6)"] @@ -6287,6 +6671,20 @@ dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pyde doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.12.0)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0)", "sphinx-design (>=0.4.0)"] test = ["array-api-strict", "asv", "gmpy2", "hypothesis (>=6.30)", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] +[[package]] +name = "segtok" +version = "1.5.11" +description = "sentence segmentation and word tokenization tools" +optional = false +python-versions = "*" +files = [ + {file = "segtok-1.5.11-py3-none-any.whl", hash = "sha256:910616b76198c3141b2772df530270d3b706e42ae69a5b30ef115c7bd5d1501a"}, + {file = "segtok-1.5.11.tar.gz", hash = "sha256:8ab2dd44245bcbfec25b575dc4618473bbdf2af8c2649698cd5a370f42f3db23"}, +] + +[package.dependencies] +regex = "*" + [[package]] name = "semver" version = "3.0.2" @@ -6314,20 +6712,97 @@ nativelib = ["pyobjc-framework-Cocoa", "pywin32"] objc = ["pyobjc-framework-Cocoa"] win32 = ["pywin32"] +[[package]] +name = "sentence-transformers" +version = "3.0.1" +description = "Multilingual text embeddings" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "sentence_transformers-3.0.1-py3-none-any.whl", hash = "sha256:01050cc4053c49b9f5b78f6980b5a72db3fd3a0abb9169b1792ac83875505ee6"}, + {file = "sentence_transformers-3.0.1.tar.gz", hash = "sha256:8a3d2c537cc4d1014ccc20ac92be3d6135420a3bc60ae29a3a8a9b4bb35fbff6"}, +] + +[package.dependencies] +huggingface-hub = ">=0.15.1" +numpy = "*" +Pillow = "*" +scikit-learn = "*" +scipy = "*" +torch = ">=1.11.0" +tqdm = "*" +transformers = ">=4.34.0,<5.0.0" + +[package.extras] +dev = ["accelerate (>=0.20.3)", "datasets", "pre-commit", "pytest", "ruff (>=0.3.0)"] +train = ["accelerate (>=0.20.3)", "datasets"] + +[[package]] +name = "sentry-sdk" +version = "2.10.0" +description = "Python client for Sentry (https://sentry.io)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "sentry_sdk-2.10.0-py2.py3-none-any.whl", hash = "sha256:87b3d413c87d8e7f816cc9334bff255a83d8b577db2b22042651c30c19c09190"}, + {file = "sentry_sdk-2.10.0.tar.gz", hash = "sha256:545fcc6e36c335faa6d6cda84669b6e17025f31efbf3b2211ec14efe008b75d1"}, +] + +[package.dependencies] +certifi = "*" +fastapi = {version = ">=0.79.0", optional = true, markers = "extra == \"fastapi\""} +urllib3 = ">=1.26.11" + +[package.extras] +aiohttp = ["aiohttp (>=3.5)"] +anthropic = ["anthropic (>=0.16)"] +arq = ["arq (>=0.23)"] +asyncpg = ["asyncpg (>=0.23)"] +beam = ["apache-beam (>=2.12)"] +bottle = ["bottle (>=0.12.13)"] +celery = ["celery (>=3)"] +celery-redbeat = ["celery-redbeat (>=2)"] +chalice = ["chalice (>=1.16.0)"] +clickhouse-driver = ["clickhouse-driver (>=0.2.0)"] +django = ["django (>=1.8)"] +falcon = ["falcon (>=1.4)"] +fastapi = ["fastapi (>=0.79.0)"] +flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"] +grpcio = ["grpcio (>=1.21.1)", "protobuf (>=3.8.0)"] +httpx = ["httpx (>=0.16.0)"] +huey = ["huey (>=2)"] +huggingface-hub = ["huggingface-hub (>=0.22)"] +langchain = ["langchain (>=0.0.210)"] +loguru = ["loguru (>=0.5)"] +openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"] +opentelemetry = ["opentelemetry-distro (>=0.35b0)"] +opentelemetry-experimental = ["opentelemetry-instrumentation-aio-pika (==0.46b0)", "opentelemetry-instrumentation-aiohttp-client (==0.46b0)", "opentelemetry-instrumentation-aiopg (==0.46b0)", "opentelemetry-instrumentation-asgi (==0.46b0)", "opentelemetry-instrumentation-asyncio (==0.46b0)", "opentelemetry-instrumentation-asyncpg (==0.46b0)", "opentelemetry-instrumentation-aws-lambda (==0.46b0)", "opentelemetry-instrumentation-boto (==0.46b0)", "opentelemetry-instrumentation-boto3sqs (==0.46b0)", "opentelemetry-instrumentation-botocore (==0.46b0)", "opentelemetry-instrumentation-cassandra (==0.46b0)", "opentelemetry-instrumentation-celery (==0.46b0)", "opentelemetry-instrumentation-confluent-kafka (==0.46b0)", "opentelemetry-instrumentation-dbapi (==0.46b0)", "opentelemetry-instrumentation-django (==0.46b0)", "opentelemetry-instrumentation-elasticsearch (==0.46b0)", "opentelemetry-instrumentation-falcon (==0.46b0)", "opentelemetry-instrumentation-fastapi (==0.46b0)", "opentelemetry-instrumentation-flask (==0.46b0)", "opentelemetry-instrumentation-grpc (==0.46b0)", "opentelemetry-instrumentation-httpx (==0.46b0)", "opentelemetry-instrumentation-jinja2 (==0.46b0)", "opentelemetry-instrumentation-kafka-python (==0.46b0)", "opentelemetry-instrumentation-logging (==0.46b0)", "opentelemetry-instrumentation-mysql (==0.46b0)", "opentelemetry-instrumentation-mysqlclient (==0.46b0)", "opentelemetry-instrumentation-pika (==0.46b0)", "opentelemetry-instrumentation-psycopg (==0.46b0)", "opentelemetry-instrumentation-psycopg2 (==0.46b0)", "opentelemetry-instrumentation-pymemcache (==0.46b0)", "opentelemetry-instrumentation-pymongo (==0.46b0)", "opentelemetry-instrumentation-pymysql (==0.46b0)", "opentelemetry-instrumentation-pyramid (==0.46b0)", "opentelemetry-instrumentation-redis (==0.46b0)", "opentelemetry-instrumentation-remoulade (==0.46b0)", "opentelemetry-instrumentation-requests (==0.46b0)", "opentelemetry-instrumentation-sklearn (==0.46b0)", "opentelemetry-instrumentation-sqlalchemy (==0.46b0)", "opentelemetry-instrumentation-sqlite3 (==0.46b0)", "opentelemetry-instrumentation-starlette (==0.46b0)", "opentelemetry-instrumentation-system-metrics (==0.46b0)", "opentelemetry-instrumentation-threading (==0.46b0)", "opentelemetry-instrumentation-tornado (==0.46b0)", "opentelemetry-instrumentation-tortoiseorm (==0.46b0)", "opentelemetry-instrumentation-urllib (==0.46b0)", "opentelemetry-instrumentation-urllib3 (==0.46b0)", "opentelemetry-instrumentation-wsgi (==0.46b0)"] +pure-eval = ["asttokens", "executing", "pure-eval"] +pymongo = ["pymongo (>=3.1)"] +pyspark = ["pyspark (>=2.4.4)"] +quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] +rq = ["rq (>=0.6)"] +sanic = ["sanic (>=0.8)"] +sqlalchemy = ["sqlalchemy (>=1.2)"] +starlette = ["starlette (>=0.19.1)"] +starlite = ["starlite (>=1.48)"] +tornado = ["tornado (>=6)"] + [[package]] name = "setuptools" -version = "70.0.0" +version = "71.0.4" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-70.0.0-py3-none-any.whl", hash = "sha256:54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4"}, - {file = "setuptools-70.0.0.tar.gz", hash = "sha256:f211a66637b8fa059bb28183da127d4e86396c991a942b028c6650d4319c3fd0"}, + {file = "setuptools-71.0.4-py3-none-any.whl", hash = "sha256:ed2feca703be3bdbd94e6bb17365d91c6935c6b2a8d0bb09b66a2c435ba0b1a5"}, + {file = "setuptools-71.0.4.tar.gz", hash = "sha256:48297e5d393a62b7cb2a10b8f76c63a73af933bd809c9e0d0d6352a1a0135dd8"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "shellingham" @@ -6627,64 +7102,64 @@ files = [ [[package]] name = "sqlalchemy" -version = "2.0.30" +version = "2.0.31" description = "Database Abstraction Library" optional = false python-versions = ">=3.7" files = [ - {file = "SQLAlchemy-2.0.30-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3b48154678e76445c7ded1896715ce05319f74b1e73cf82d4f8b59b46e9c0ddc"}, - {file = "SQLAlchemy-2.0.30-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2753743c2afd061bb95a61a51bbb6a1a11ac1c44292fad898f10c9839a7f75b2"}, - {file = "SQLAlchemy-2.0.30-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7bfc726d167f425d4c16269a9a10fe8630ff6d14b683d588044dcef2d0f6be7"}, - {file = "SQLAlchemy-2.0.30-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4f61ada6979223013d9ab83a3ed003ded6959eae37d0d685db2c147e9143797"}, - {file = "SQLAlchemy-2.0.30-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a365eda439b7a00732638f11072907c1bc8e351c7665e7e5da91b169af794af"}, - {file = "SQLAlchemy-2.0.30-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bba002a9447b291548e8d66fd8c96a6a7ed4f2def0bb155f4f0a1309fd2735d5"}, - {file = "SQLAlchemy-2.0.30-cp310-cp310-win32.whl", hash = "sha256:0138c5c16be3600923fa2169532205d18891b28afa817cb49b50e08f62198bb8"}, - {file = "SQLAlchemy-2.0.30-cp310-cp310-win_amd64.whl", hash = "sha256:99650e9f4cf3ad0d409fed3eec4f071fadd032e9a5edc7270cd646a26446feeb"}, - {file = "SQLAlchemy-2.0.30-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:955991a09f0992c68a499791a753523f50f71a6885531568404fa0f231832aa0"}, - {file = "SQLAlchemy-2.0.30-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f69e4c756ee2686767eb80f94c0125c8b0a0b87ede03eacc5c8ae3b54b99dc46"}, - {file = "SQLAlchemy-2.0.30-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69c9db1ce00e59e8dd09d7bae852a9add716efdc070a3e2068377e6ff0d6fdaa"}, - {file = "SQLAlchemy-2.0.30-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1429a4b0f709f19ff3b0cf13675b2b9bfa8a7e79990003207a011c0db880a13"}, - {file = "SQLAlchemy-2.0.30-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:efedba7e13aa9a6c8407c48facfdfa108a5a4128e35f4c68f20c3407e4376aa9"}, - {file = "SQLAlchemy-2.0.30-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:16863e2b132b761891d6c49f0a0f70030e0bcac4fd208117f6b7e053e68668d0"}, - {file = "SQLAlchemy-2.0.30-cp311-cp311-win32.whl", hash = "sha256:2ecabd9ccaa6e914e3dbb2aa46b76dede7eadc8cbf1b8083c94d936bcd5ffb49"}, - {file = "SQLAlchemy-2.0.30-cp311-cp311-win_amd64.whl", hash = "sha256:0b3f4c438e37d22b83e640f825ef0f37b95db9aa2d68203f2c9549375d0b2260"}, - {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5a79d65395ac5e6b0c2890935bad892eabb911c4aa8e8015067ddb37eea3d56c"}, - {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9a5baf9267b752390252889f0c802ea13b52dfee5e369527da229189b8bd592e"}, - {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cb5a646930c5123f8461f6468901573f334c2c63c795b9af350063a736d0134"}, - {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:296230899df0b77dec4eb799bcea6fbe39a43707ce7bb166519c97b583cfcab3"}, - {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c62d401223f468eb4da32627bffc0c78ed516b03bb8a34a58be54d618b74d472"}, - {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3b69e934f0f2b677ec111b4d83f92dc1a3210a779f69bf905273192cf4ed433e"}, - {file = "SQLAlchemy-2.0.30-cp312-cp312-win32.whl", hash = "sha256:77d2edb1f54aff37e3318f611637171e8ec71472f1fdc7348b41dcb226f93d90"}, - {file = "SQLAlchemy-2.0.30-cp312-cp312-win_amd64.whl", hash = "sha256:b6c7ec2b1f4969fc19b65b7059ed00497e25f54069407a8701091beb69e591a5"}, - {file = "SQLAlchemy-2.0.30-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5a8e3b0a7e09e94be7510d1661339d6b52daf202ed2f5b1f9f48ea34ee6f2d57"}, - {file = "SQLAlchemy-2.0.30-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b60203c63e8f984df92035610c5fb76d941254cf5d19751faab7d33b21e5ddc0"}, - {file = "SQLAlchemy-2.0.30-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1dc3eabd8c0232ee8387fbe03e0a62220a6f089e278b1f0aaf5e2d6210741ad"}, - {file = "SQLAlchemy-2.0.30-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:40ad017c672c00b9b663fcfcd5f0864a0a97828e2ee7ab0c140dc84058d194cf"}, - {file = "SQLAlchemy-2.0.30-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e42203d8d20dc704604862977b1470a122e4892791fe3ed165f041e4bf447a1b"}, - {file = "SQLAlchemy-2.0.30-cp37-cp37m-win32.whl", hash = "sha256:2a4f4da89c74435f2bc61878cd08f3646b699e7d2eba97144030d1be44e27584"}, - {file = "SQLAlchemy-2.0.30-cp37-cp37m-win_amd64.whl", hash = "sha256:b6bf767d14b77f6a18b6982cbbf29d71bede087edae495d11ab358280f304d8e"}, - {file = "SQLAlchemy-2.0.30-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc0c53579650a891f9b83fa3cecd4e00218e071d0ba00c4890f5be0c34887ed3"}, - {file = "SQLAlchemy-2.0.30-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:311710f9a2ee235f1403537b10c7687214bb1f2b9ebb52702c5aa4a77f0b3af7"}, - {file = "SQLAlchemy-2.0.30-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:408f8b0e2c04677e9c93f40eef3ab22f550fecb3011b187f66a096395ff3d9fd"}, - {file = "SQLAlchemy-2.0.30-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37a4b4fb0dd4d2669070fb05b8b8824afd0af57587393015baee1cf9890242d9"}, - {file = "SQLAlchemy-2.0.30-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a943d297126c9230719c27fcbbeab57ecd5d15b0bd6bfd26e91bfcfe64220621"}, - {file = "SQLAlchemy-2.0.30-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0a089e218654e740a41388893e090d2e2c22c29028c9d1353feb38638820bbeb"}, - {file = "SQLAlchemy-2.0.30-cp38-cp38-win32.whl", hash = "sha256:fa561138a64f949f3e889eb9ab8c58e1504ab351d6cf55259dc4c248eaa19da6"}, - {file = "SQLAlchemy-2.0.30-cp38-cp38-win_amd64.whl", hash = "sha256:7d74336c65705b986d12a7e337ba27ab2b9d819993851b140efdf029248e818e"}, - {file = "SQLAlchemy-2.0.30-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae8c62fe2480dd61c532ccafdbce9b29dacc126fe8be0d9a927ca3e699b9491a"}, - {file = "SQLAlchemy-2.0.30-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2383146973a15435e4717f94c7509982770e3e54974c71f76500a0136f22810b"}, - {file = "SQLAlchemy-2.0.30-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8409de825f2c3b62ab15788635ccaec0c881c3f12a8af2b12ae4910a0a9aeef6"}, - {file = "SQLAlchemy-2.0.30-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0094c5dc698a5f78d3d1539853e8ecec02516b62b8223c970c86d44e7a80f6c7"}, - {file = "SQLAlchemy-2.0.30-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:edc16a50f5e1b7a06a2dcc1f2205b0b961074c123ed17ebda726f376a5ab0953"}, - {file = "SQLAlchemy-2.0.30-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f7703c2010355dd28f53deb644a05fc30f796bd8598b43f0ba678878780b6e4c"}, - {file = "SQLAlchemy-2.0.30-cp39-cp39-win32.whl", hash = "sha256:1f9a727312ff6ad5248a4367358e2cf7e625e98b1028b1d7ab7b806b7d757513"}, - {file = "SQLAlchemy-2.0.30-cp39-cp39-win_amd64.whl", hash = "sha256:a0ef36b28534f2a5771191be6edb44cc2673c7b2edf6deac6562400288664221"}, - {file = "SQLAlchemy-2.0.30-py3-none-any.whl", hash = "sha256:7108d569d3990c71e26a42f60474b4c02c8586c4681af5fd67e51a044fdea86a"}, - {file = "SQLAlchemy-2.0.30.tar.gz", hash = "sha256:2b1708916730f4830bc69d6f49d37f7698b5bd7530aca7f04f785f8849e95255"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f2a213c1b699d3f5768a7272de720387ae0122f1becf0901ed6eaa1abd1baf6c"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9fea3d0884e82d1e33226935dac990b967bef21315cbcc894605db3441347443"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3ad7f221d8a69d32d197e5968d798217a4feebe30144986af71ada8c548e9fa"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2bee229715b6366f86a95d497c347c22ddffa2c7c96143b59a2aa5cc9eebbc"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cd5b94d4819c0c89280b7c6109c7b788a576084bf0a480ae17c227b0bc41e109"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:750900a471d39a7eeba57580b11983030517a1f512c2cb287d5ad0fcf3aebd58"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-win32.whl", hash = "sha256:7bd112be780928c7f493c1a192cd8c5fc2a2a7b52b790bc5a84203fb4381c6be"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-win_amd64.whl", hash = "sha256:5a48ac4d359f058474fadc2115f78a5cdac9988d4f99eae44917f36aa1476327"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f68470edd70c3ac3b6cd5c2a22a8daf18415203ca1b036aaeb9b0fb6f54e8298"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e2c38c2a4c5c634fe6c3c58a789712719fa1bf9b9d6ff5ebfce9a9e5b89c1ca"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd15026f77420eb2b324dcb93551ad9c5f22fab2c150c286ef1dc1160f110203"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2196208432deebdfe3b22185d46b08f00ac9d7b01284e168c212919891289396"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:352b2770097f41bff6029b280c0e03b217c2dcaddc40726f8f53ed58d8a85da4"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:56d51ae825d20d604583f82c9527d285e9e6d14f9a5516463d9705dab20c3740"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-win32.whl", hash = "sha256:6e2622844551945db81c26a02f27d94145b561f9d4b0c39ce7bfd2fda5776dac"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-win_amd64.whl", hash = "sha256:ccaf1b0c90435b6e430f5dd30a5aede4764942a695552eb3a4ab74ed63c5b8d3"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3b74570d99126992d4b0f91fb87c586a574a5872651185de8297c6f90055ae42"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f77c4f042ad493cb8595e2f503c7a4fe44cd7bd59c7582fd6d78d7e7b8ec52c"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd1591329333daf94467e699e11015d9c944f44c94d2091f4ac493ced0119449"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74afabeeff415e35525bf7a4ecdab015f00e06456166a2eba7590e49f8db940e"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b9c01990d9015df2c6f818aa8f4297d42ee71c9502026bb074e713d496e26b67"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:66f63278db425838b3c2b1c596654b31939427016ba030e951b292e32b99553e"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-win32.whl", hash = "sha256:0b0f658414ee4e4b8cbcd4a9bb0fd743c5eeb81fc858ca517217a8013d282c96"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-win_amd64.whl", hash = "sha256:fa4b1af3e619b5b0b435e333f3967612db06351217c58bfb50cee5f003db2a5a"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f43e93057cf52a227eda401251c72b6fbe4756f35fa6bfebb5d73b86881e59b0"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d337bf94052856d1b330d5fcad44582a30c532a2463776e1651bd3294ee7e58b"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c06fb43a51ccdff3b4006aafee9fcf15f63f23c580675f7734245ceb6b6a9e05"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:b6e22630e89f0e8c12332b2b4c282cb01cf4da0d26795b7eae16702a608e7ca1"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:79a40771363c5e9f3a77f0e28b3302801db08040928146e6808b5b7a40749c88"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-win32.whl", hash = "sha256:501ff052229cb79dd4c49c402f6cb03b5a40ae4771efc8bb2bfac9f6c3d3508f"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-win_amd64.whl", hash = "sha256:597fec37c382a5442ffd471f66ce12d07d91b281fd474289356b1a0041bdf31d"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:dc6d69f8829712a4fd799d2ac8d79bdeff651c2301b081fd5d3fe697bd5b4ab9"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:23b9fbb2f5dd9e630db70fbe47d963c7779e9c81830869bd7d137c2dc1ad05fb"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a21c97efcbb9f255d5c12a96ae14da873233597dfd00a3a0c4ce5b3e5e79704"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26a6a9837589c42b16693cf7bf836f5d42218f44d198f9343dd71d3164ceeeac"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc251477eae03c20fae8db9c1c23ea2ebc47331bcd73927cdcaecd02af98d3c3"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2fd17e3bb8058359fa61248c52c7b09a97cf3c820e54207a50af529876451808"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-win32.whl", hash = "sha256:c76c81c52e1e08f12f4b6a07af2b96b9b15ea67ccdd40ae17019f1c373faa227"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-win_amd64.whl", hash = "sha256:4b600e9a212ed59355813becbcf282cfda5c93678e15c25a0ef896b354423238"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b6cf796d9fcc9b37011d3f9936189b3c8074a02a4ed0c0fbbc126772c31a6d4"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:78fe11dbe37d92667c2c6e74379f75746dc947ee505555a0197cfba9a6d4f1a4"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fc47dc6185a83c8100b37acda27658fe4dbd33b7d5e7324111f6521008ab4fe"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a41514c1a779e2aa9a19f67aaadeb5cbddf0b2b508843fcd7bafdf4c6864005"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:afb6dde6c11ea4525318e279cd93c8734b795ac8bb5dda0eedd9ebaca7fa23f1"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3f9faef422cfbb8fd53716cd14ba95e2ef655400235c3dfad1b5f467ba179c8c"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-win32.whl", hash = "sha256:fc6b14e8602f59c6ba893980bea96571dd0ed83d8ebb9c4479d9ed5425d562e9"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-win_amd64.whl", hash = "sha256:3cb8a66b167b033ec72c3812ffc8441d4e9f5f78f5e31e54dcd4c90a4ca5bebc"}, + {file = "SQLAlchemy-2.0.31-py3-none-any.whl", hash = "sha256:69f3e3c08867a8e4856e92d7afb618b95cdee18e0bc1647b77599722c9a28911"}, + {file = "SQLAlchemy-2.0.31.tar.gz", hash = "sha256:b607489dd4a54de56984a0c7656247504bd5523d9d0ba799aef59d4add009484"}, ] [package.dependencies] -greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} +greenlet = {version = "!=0.4.17", markers = "python_version < \"3.13\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} typing-extensions = ">=4.6.0" [package.extras] @@ -6714,13 +7189,13 @@ sqlcipher = ["sqlcipher3_binary"] [[package]] name = "squarify" -version = "0.4.3" +version = "0.4.4" description = "Pure Python implementation of the squarify treemap layout algorithm" optional = false python-versions = "*" files = [ - {file = "squarify-0.4.3-py3-none-any.whl", hash = "sha256:bec7011e0c7f4103fe57a1c16a7c091d9dc1be0f23d774e1c568b748a6f818f6"}, - {file = "squarify-0.4.3.tar.gz", hash = "sha256:54091f6ad175f7f201f8934574e647ce1b50dedc478c5fd968688eb7d7469f95"}, + {file = "squarify-0.4.4-py3-none-any.whl", hash = "sha256:d7597724e29d48aa14fd2f551060d6b09e1f0a67e4cd3ea329fe03b4c9a56f11"}, + {file = "squarify-0.4.4.tar.gz", hash = "sha256:b8a110c8dc5f1cd1402ca12d79764a081e90bfc445346cfa166df929753ecb46"}, ] [[package]] @@ -6808,34 +7283,37 @@ full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7 [[package]] name = "structlog" -version = "24.2.0" +version = "24.4.0" description = "Structured Logging for Python" optional = false python-versions = ">=3.8" files = [ - {file = "structlog-24.2.0-py3-none-any.whl", hash = "sha256:983bd49f70725c5e1e3867096c0c09665918936b3db27341b41d294283d7a48a"}, - {file = "structlog-24.2.0.tar.gz", hash = "sha256:0e3fe74924a6d8857d3f612739efb94c72a7417d7c7c008d12276bca3b5bf13b"}, + {file = "structlog-24.4.0-py3-none-any.whl", hash = "sha256:597f61e80a91cc0749a9fd2a098ed76715a1c8a01f73e336b746504d1aad7610"}, + {file = "structlog-24.4.0.tar.gz", hash = "sha256:b27bfecede327a6d2da5fbc96bd859f114ecc398a6389d664f62085ee7ae6fc4"}, ] [package.extras] dev = ["freezegun (>=0.2.8)", "mypy (>=1.4)", "pretend", "pytest (>=6.0)", "pytest-asyncio (>=0.17)", "rich", "simplejson", "twisted"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-mermaid", "sphinxext-opengraph", "twisted"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-mermaid", "sphinxext-opengraph", "twisted"] tests = ["freezegun (>=0.2.8)", "pretend", "pytest (>=6.0)", "pytest-asyncio (>=0.17)", "simplejson"] typing = ["mypy (>=1.4)", "rich", "twisted"] [[package]] name = "sympy" -version = "1.12.1" +version = "1.13.1" description = "Computer algebra system (CAS) in Python" optional = false python-versions = ">=3.8" files = [ - {file = "sympy-1.12.1-py3-none-any.whl", hash = "sha256:9b2cbc7f1a640289430e13d2a56f02f867a1da0190f2f99d8968c2f74da0e515"}, - {file = "sympy-1.12.1.tar.gz", hash = "sha256:2877b03f998cd8c08f07cd0de5b767119cd3ef40d09f41c30d722f6686b0fb88"}, + {file = "sympy-1.13.1-py3-none-any.whl", hash = "sha256:db36cdc64bf61b9b24578b6f7bab1ecdd2452cf008f34faa33776680c26d66f8"}, + {file = "sympy-1.13.1.tar.gz", hash = "sha256:9cebf7e04ff162015ce31c9c6c9144daa34a93bd082f54fd8f12deca4f47515f"}, ] [package.dependencies] -mpmath = ">=1.1.0,<1.4.0" +mpmath = ">=1.1.0,<1.4" + +[package.extras] +dev = ["hypothesis (>=6.70.0)", "pytest (>=7.1.0)"] [[package]] name = "tabulate" @@ -6889,15 +7367,28 @@ files = [ [package.extras] dev = ["nox"] +[[package]] +name = "tbb" +version = "2021.13.0" +description = "Intel® oneAPI Threading Building Blocks (oneTBB)" +optional = false +python-versions = "*" +files = [ + {file = "tbb-2021.13.0-py2.py3-none-manylinux1_i686.whl", hash = "sha256:a2567725329639519d46d92a2634cf61e76601dac2f777a05686fea546c4fe4f"}, + {file = "tbb-2021.13.0-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:aaf667e92849adb012b8874d6393282afc318aca4407fc62f912ee30a22da46a"}, + {file = "tbb-2021.13.0-py3-none-win32.whl", hash = "sha256:6669d26703e9943f6164c6407bd4a237a45007e79b8d3832fe6999576eaaa9ef"}, + {file = "tbb-2021.13.0-py3-none-win_amd64.whl", hash = "sha256:3528a53e4bbe64b07a6112b4c5a00ff3c61924ee46c9c68e004a1ac7ad1f09c3"}, +] + [[package]] name = "tenacity" -version = "8.3.0" +version = "8.5.0" description = "Retry code until it succeeds" optional = false python-versions = ">=3.8" files = [ - {file = "tenacity-8.3.0-py3-none-any.whl", hash = "sha256:3649f6443dbc0d9b01b9d8020a9c4ec7a1ff5f6f3c6c8a036ef371f573fe9185"}, - {file = "tenacity-8.3.0.tar.gz", hash = "sha256:953d4e6ad24357bceffbc9707bc74349aca9d245f68eb65419cf0c249a1949a2"}, + {file = "tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687"}, + {file = "tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78"}, ] [package.extras] @@ -6927,45 +7418,32 @@ typing = ["mypy (>=1.6,<2.0)", "traitlets (>=5.11.1)"] [[package]] name = "thinc" -version = "8.2.4" +version = "8.2.5" description = "A refreshing functional take on deep learning, compatible with your favorite libraries" optional = false python-versions = ">=3.6" files = [ - {file = "thinc-8.2.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:aaae34c28ebc7a0ba980e6c774f148e272375ff7d4ef6ae2977698edae052e52"}, - {file = "thinc-8.2.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a6c807cb75a22a17e5333377aff203dabf10daa457ce9e78b19f499a44dd816"}, - {file = "thinc-8.2.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b53c092ab30abb9a3b46ef72a8a6af76db42822b550eff778b0decf95af572c4"}, - {file = "thinc-8.2.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5724ea71dbdbb0d0168471884b9b6909bedaccfda01524c5e775a6fbc39d1bc7"}, - {file = "thinc-8.2.4-cp310-cp310-win_amd64.whl", hash = "sha256:bb14e49ddb15770201682eda8381db6393f76580c1eb72d45e77e1202598116e"}, - {file = "thinc-8.2.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ccc58e47bc285e9afbf92ed6104f555abfa285a4b92198d955d344c4c1942607"}, - {file = "thinc-8.2.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:baa4af044bfcaf9df6a02d6c6d6e96c960da540478a522daabfbde8923df3554"}, - {file = "thinc-8.2.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b0e34bf322516a039e45c1da72eb82bcc97eb1f7c232b66b88f0c86f15a1202"}, - {file = "thinc-8.2.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc8ab48d19cd69ad9a0de2bbe49b7c20a91150faeb119638bea4c502c52b77f"}, - {file = "thinc-8.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:9f8c6c006b7cbe3ebb543c224159b004b52a8ff8922615577656e1458ee4bbf0"}, - {file = "thinc-8.2.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:997a1a399af074b34e25695f37ad48f8437e7c150705891f4db89aeb430df35a"}, - {file = "thinc-8.2.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8e28ba753cdf925ac25b52ea6c4baf5104c6ed6874d9e3dfe768ff98d5118db1"}, - {file = "thinc-8.2.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5c3874361a1d3c469dd7c9054d4d16b7afcf791e9c47705766d690685fe702d"}, - {file = "thinc-8.2.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4a22e76e4651fb6b209cfba2e1c167e8537286ae35fb87769a17af491f995b5"}, - {file = "thinc-8.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:ebfd9d79d2bdadec551cb9ca8c7fdeacb56db642158c56cdb039de47e9aad995"}, - {file = "thinc-8.2.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f46f0f58f3bc02beeee5977a991335b845cb15bf1836ee8d8d15b613805c0016"}, - {file = "thinc-8.2.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d879df0997959f9d7087b0e392e72e120bde5613eb8a7c1c453370c48284e7f"}, - {file = "thinc-8.2.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:795a7a1a03767a40d1e2a19fcf25c552a8d8765c78c1837514cabf5fe98817b9"}, - {file = "thinc-8.2.4-cp36-cp36m-win_amd64.whl", hash = "sha256:a276287e55b0ec50c7e8f1acef28f5353c59234af1efc54a19516328f50a6f68"}, - {file = "thinc-8.2.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:21a5cb6633b4af8b49a18a3088cdcbc59756ce6a4202574f4151dd4df18bab49"}, - {file = "thinc-8.2.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca9fcddc3852b733e4754f37bb4d20693192171f1e3e9714b00abe5d74fffeb"}, - {file = "thinc-8.2.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd67e210a4a67781c9864ef45e27ec009c1f4234c737c4a2d0964aeebd3d39a1"}, - {file = "thinc-8.2.4-cp37-cp37m-win_amd64.whl", hash = "sha256:37ea70230bc4a149905e21ba620ad78ec5362b3cf8f9d1233523d6ec03a3b8e5"}, - {file = "thinc-8.2.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5586115b2f3c1c9ecc8f9dbed4a26a46d44c40e8f6be0e58e63fb673271cd0d9"}, - {file = "thinc-8.2.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:334097a26742ff6552a2b1ff347207b8ce4048a70756e33849bab07122f13403"}, - {file = "thinc-8.2.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a124684987554170c043ae9c497c5ebbd619a9cf2053462ff6b7e359541fbafd"}, - {file = "thinc-8.2.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8f9e147b41a1e02c232d5cc4b2a333b47a245d9e87dbcd1b3f11636332a1ae5"}, - {file = "thinc-8.2.4-cp38-cp38-win_amd64.whl", hash = "sha256:58b172d3546ecd14d257e2f37e7b9784941caa919544604137810a5477f87c99"}, - {file = "thinc-8.2.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03ab79a1734db519bd355d1c7eb41a2425d4d5c1ad4f416ea4e09cd42b8854a8"}, - {file = "thinc-8.2.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c466289b6fb40f477e32f99647e03256d0b1d775707778dac07973fd352c5220"}, - {file = "thinc-8.2.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbffb3d284c9a54cf8bfee606e47028a27a2d11b0b1e2b83137cc03169e8a8f1"}, - {file = "thinc-8.2.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abeb742352a106359ac76f048c0f4af745c59c75e02b68cc4d62cde20fcca0c5"}, - {file = "thinc-8.2.4-cp39-cp39-win_amd64.whl", hash = "sha256:ed514b3edb185c5531fcfd77a7b0a43c196a269f1e157a025d8138076ba6328d"}, - {file = "thinc-8.2.4.tar.gz", hash = "sha256:9383b39f286291519ebbb6454bab76404992599b0cbdfaec56b2f985023186a7"}, + {file = "thinc-8.2.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dc267f6aad80a681a85f50383afe91da9e2bec56fefdda86bfa2e4f529bef191"}, + {file = "thinc-8.2.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d80f1e497971c9fa0938f5cc8fe607bbe87356b405fb7bbc3ff9f32fb4eed3bb"}, + {file = "thinc-8.2.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0933adbd3e65e30d3bef903e77a368bc8a41bed34b0d18df6d4fc0536908e21f"}, + {file = "thinc-8.2.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54bac2ba23b208fdaf267cd6113d26a5ecbb3b0e0c6015dff784ae6a9c5e78ca"}, + {file = "thinc-8.2.5-cp310-cp310-win_amd64.whl", hash = "sha256:399260197ef3f8d9600315fc5b5a1d5940400fceb0361de642e9fe3506d82385"}, + {file = "thinc-8.2.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a75c0de3340afed594beda293661de145f3842873df56d9989bc338148f13fab"}, + {file = "thinc-8.2.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6b166d1a22003ee03bc236370fff2884744c1fb758a6209a2512d305773d07d7"}, + {file = "thinc-8.2.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34db8a023b9f70645fdf06c510584ba6d8b97ec53c1e094f42d95652bf8c875f"}, + {file = "thinc-8.2.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8901b30db1071ea8d5e4437429c8632535bf5ed87938ce3bb5057bed9f15aed8"}, + {file = "thinc-8.2.5-cp311-cp311-win_amd64.whl", hash = "sha256:8ef5d46d62e31f2450224ab22391a606cf427b13e20cfc570f70422e2f333872"}, + {file = "thinc-8.2.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9fc26697e2358c71a5fe243d52e98ae67ee1a3b314eead5031845b6d1c0d121c"}, + {file = "thinc-8.2.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8e299d4dc41107385d6d14d8604a060825798a031cabe2b894b22f9d75d9eaad"}, + {file = "thinc-8.2.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8a8f2f249f2be9a5ce2a81a6efe7503b68be7b57e47ad54ab28204e1f0c723b"}, + {file = "thinc-8.2.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87e729f33c76ec6df9b375989743252ab880d79f3a2b4175169b21dece90f102"}, + {file = "thinc-8.2.5-cp312-cp312-win_amd64.whl", hash = "sha256:c5f750ea2dd32ca6d46947025dacfc0f6037340c4e5f7adb9af84c75f65aa7d8"}, + {file = "thinc-8.2.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bb97e2f699a3df16112ef5460cbfb0c9189a5fbc0e76bcf170ed7d995bdce367"}, + {file = "thinc-8.2.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5c78fb218273894168d1ca2dd3a20f28dba5a7fa698c4f2a2fc425eda2086cfc"}, + {file = "thinc-8.2.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc27da534807a2addd1c3d2a3d19f99e3eb67fdbce81c21f4e4c8bfa94ac15b"}, + {file = "thinc-8.2.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b884e56eaeb9e5c7bfeb1c8810a3cbad19a599b33b9f3152b90b67f468471ac"}, + {file = "thinc-8.2.5-cp39-cp39-win_amd64.whl", hash = "sha256:df2138cf379061017ecb8bf609a8857e7904709ef0a9a2252783c16f67a2b749"}, + {file = "thinc-8.2.5.tar.gz", hash = "sha256:c2963791c934cc7fbd8f9b942d571cac79892ad11630bfca690a868c32752b75"}, ] [package.dependencies] @@ -6974,7 +7452,7 @@ catalogue = ">=2.0.4,<2.1.0" confection = ">=0.0.1,<1.0.0" cymem = ">=2.0.2,<2.1.0" murmurhash = ">=1.0.2,<1.1.0" -numpy = {version = ">=1.19.0", markers = "python_version >= \"3.9\""} +numpy = {version = ">=1.19.0,<2.0.0", markers = "python_version >= \"3.9\""} packaging = ">=20.0" preshed = ">=3.0.2,<3.1.0" pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<3.0.0" @@ -7228,15 +7706,69 @@ files = [ [[package]] name = "tomlkit" -version = "0.12.5" +version = "0.13.0" description = "Style preserving TOML library" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomlkit-0.12.5-py3-none-any.whl", hash = "sha256:af914f5a9c59ed9d0762c7b64d3b5d5df007448eb9cd2edc8a46b1eafead172f"}, - {file = "tomlkit-0.12.5.tar.gz", hash = "sha256:eef34fba39834d4d6b73c9ba7f3e4d1c417a4e56f89a7e96e090dd0d24b8fb3c"}, + {file = "tomlkit-0.13.0-py3-none-any.whl", hash = "sha256:7075d3042d03b80f603482d69bf0c8f345c2b30e41699fd8883227f89972b264"}, + {file = "tomlkit-0.13.0.tar.gz", hash = "sha256:08ad192699734149f5b97b45f1f18dad7eb1b6d16bc72ad0c2335772650d7b72"}, ] +[[package]] +name = "torch" +version = "2.3.1" +description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "torch-2.3.1-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:605a25b23944be5ab7c3467e843580e1d888b8066e5aaf17ff7bf9cc30001cc3"}, + {file = "torch-2.3.1-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:f2357eb0965583a0954d6f9ad005bba0091f956aef879822274b1bcdb11bd308"}, + {file = "torch-2.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:32b05fe0d1ada7f69c9f86c14ff69b0ef1957a5a54199bacba63d22d8fab720b"}, + {file = "torch-2.3.1-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:7c09a94362778428484bcf995f6004b04952106aee0ef45ff0b4bab484f5498d"}, + {file = "torch-2.3.1-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:b2ec81b61bb094ea4a9dee1cd3f7b76a44555375719ad29f05c0ca8ef596ad39"}, + {file = "torch-2.3.1-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:490cc3d917d1fe0bd027057dfe9941dc1d6d8e3cae76140f5dd9a7e5bc7130ab"}, + {file = "torch-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:5802530783bd465fe66c2df99123c9a54be06da118fbd785a25ab0a88123758a"}, + {file = "torch-2.3.1-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:a7dd4ed388ad1f3d502bf09453d5fe596c7b121de7e0cfaca1e2017782e9bbac"}, + {file = "torch-2.3.1-cp312-cp312-manylinux1_x86_64.whl", hash = "sha256:a486c0b1976a118805fc7c9641d02df7afbb0c21e6b555d3bb985c9f9601b61a"}, + {file = "torch-2.3.1-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:224259821fe3e4c6f7edf1528e4fe4ac779c77addaa74215eb0b63a5c474d66c"}, + {file = "torch-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:e5fdccbf6f1334b2203a61a0e03821d5845f1421defe311dabeae2fc8fbeac2d"}, + {file = "torch-2.3.1-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:3c333dc2ebc189561514eda06e81df22bf8fb64e2384746b2cb9f04f96d1d4c8"}, + {file = "torch-2.3.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:07e9ba746832b8d069cacb45f312cadd8ad02b81ea527ec9766c0e7404bb3feb"}, + {file = "torch-2.3.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:462d1c07dbf6bb5d9d2f3316fee73a24f3d12cd8dacf681ad46ef6418f7f6626"}, + {file = "torch-2.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:ff60bf7ce3de1d43ad3f6969983f321a31f0a45df3690921720bcad6a8596cc4"}, + {file = "torch-2.3.1-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:bee0bd33dc58aa8fc8a7527876e9b9a0e812ad08122054a5bff2ce5abf005b10"}, + {file = "torch-2.3.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:aaa872abde9a3d4f91580f6396d54888620f4a0b92e3976a6034759df4b961ad"}, + {file = "torch-2.3.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:3d7a7f7ef21a7520510553dc3938b0c57c116a7daee20736a9e25cbc0e832bdc"}, + {file = "torch-2.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:4777f6cefa0c2b5fa87223c213e7b6f417cf254a45e5829be4ccd1b2a4ee1011"}, + {file = "torch-2.3.1-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:2bb5af780c55be68fe100feb0528d2edebace1d55cb2e351de735809ba7391eb"}, +] + +[package.dependencies] +filelock = "*" +fsspec = "*" +jinja2 = "*" +mkl = {version = ">=2021.1.1,<=2021.4.0", markers = "platform_system == \"Windows\""} +networkx = "*" +nvidia-cublas-cu12 = {version = "12.1.3.1", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cuda-cupti-cu12 = {version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cuda-nvrtc-cu12 = {version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cuda-runtime-cu12 = {version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cudnn-cu12 = {version = "8.9.2.26", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cufft-cu12 = {version = "11.0.2.54", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-curand-cu12 = {version = "10.3.2.106", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cusolver-cu12 = {version = "11.4.5.107", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cusparse-cu12 = {version = "12.1.0.106", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-nccl-cu12 = {version = "2.20.5", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-nvtx-cu12 = {version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +sympy = "*" +triton = {version = "2.3.1", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and python_version < \"3.12\""} +typing-extensions = ">=4.8.0" + +[package.extras] +opt-einsum = ["opt-einsum (>=3.3)"] +optree = ["optree (>=0.9.1)"] + [[package]] name = "tornado" version = "6.4.1" @@ -7360,6 +7892,29 @@ torchhub = ["filelock", "huggingface-hub (>=0.19.3,<1.0)", "importlib-metadata", video = ["av (==9.2.0)", "decord (==0.6.0)"] vision = ["Pillow (>=10.0.1,<=15.0)"] +[[package]] +name = "triton" +version = "2.3.1" +description = "A language and compiler for custom Deep Learning operations" +optional = false +python-versions = "*" +files = [ + {file = "triton-2.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c84595cbe5e546b1b290d2a58b1494df5a2ef066dd890655e5b8a8a92205c33"}, + {file = "triton-2.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9d64ae33bcb3a7a18081e3a746e8cf87ca8623ca13d2c362413ce7a486f893e"}, + {file = "triton-2.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaf80e8761a9e3498aa92e7bf83a085b31959c61f5e8ac14eedd018df6fccd10"}, + {file = "triton-2.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b13bf35a2b659af7159bf78e92798dc62d877aa991de723937329e2d382f1991"}, + {file = "triton-2.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63381e35ded3304704ea867ffde3b7cfc42c16a55b3062d41e017ef510433d66"}, + {file = "triton-2.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d968264523c7a07911c8fb51b4e0d1b920204dae71491b1fe7b01b62a31e124"}, +] + +[package.dependencies] +filelock = "*" + +[package.extras] +build = ["cmake (>=3.20)", "lit"] +tests = ["autopep8", "flake8", "isort", "numpy", "pytest", "scipy (>=1.7.1)", "torch"] +tutorials = ["matplotlib", "pandas", "tabulate", "torch"] + [[package]] name = "typer" version = "0.12.3" @@ -7390,13 +7945,13 @@ files = [ [[package]] name = "types-setuptools" -version = "70.0.0.20240524" +version = "70.3.0.20240710" description = "Typing stubs for setuptools" optional = false python-versions = ">=3.8" files = [ - {file = "types-setuptools-70.0.0.20240524.tar.gz", hash = "sha256:e31fee7b9d15ef53980526579ac6089b3ae51a005a281acf97178e90ac71aff6"}, - {file = "types_setuptools-70.0.0.20240524-py3-none-any.whl", hash = "sha256:8f5379b9948682d72a9ab531fbe52932e84c4f38deda570255f9bae3edd766bc"}, + {file = "types-setuptools-70.3.0.20240710.tar.gz", hash = "sha256:842cbf399812d2b65042c9d6ff35113bbf282dee38794779aa1f94e597bafc35"}, + {file = "types_setuptools-70.3.0.20240710-py3-none-any.whl", hash = "sha256:bd0db2a4b9f2c49ac5564be4e0fb3125c4c46b1f73eafdcbceffa5b005cceca4"}, ] [[package]] @@ -7437,13 +7992,13 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake [[package]] name = "urllib3" -version = "1.26.18" +version = "1.26.19" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ - {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, - {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, + {file = "urllib3-1.26.19-py2.py3-none-any.whl", hash = "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3"}, + {file = "urllib3-1.26.19.tar.gz", hash = "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429"}, ] [package.extras] @@ -7453,13 +8008,13 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "urllib3" -version = "2.2.1" +version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, ] [package.extras] @@ -7488,15 +8043,18 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", [[package]] name = "validators" -version = "0.28.3" +version = "0.33.0" description = "Python Data Validation for Humans™" optional = false python-versions = ">=3.8" files = [ - {file = "validators-0.28.3-py3-none-any.whl", hash = "sha256:53cafa854f13850156259d9cc479b864ee901f6a96e6b109e6fc33f98f37d99f"}, - {file = "validators-0.28.3.tar.gz", hash = "sha256:c6c79840bcde9ba77b19f6218f7738188115e27830cbaff43264bc4ed24c429d"}, + {file = "validators-0.33.0-py3-none-any.whl", hash = "sha256:134b586a98894f8139865953899fc2daeb3d0c35569552c5518f089ae43ed075"}, + {file = "validators-0.33.0.tar.gz", hash = "sha256:535867e9617f0100e676a1257ba1e206b9bfd847ddc171e4d44811f07ff0bfbf"}, ] +[package.extras] +crypto-eth-addresses = ["eth-hash[pycryptodome] (>=0.7.0)"] + [[package]] name = "wasabi" version = "1.1.3" @@ -7590,13 +8148,13 @@ wasabi = ">=0.9.1,<1.2.0" [[package]] name = "weaviate-client" -version = "4.6.4" +version = "4.6.7" description = "A python native Weaviate client" optional = false python-versions = ">=3.8" files = [ - {file = "weaviate_client-4.6.4-py3-none-any.whl", hash = "sha256:19b76fb923a5f0b6fcb7471ef3cd990d2791ede71731e53429e1066a9dbf2af2"}, - {file = "weaviate_client-4.6.4.tar.gz", hash = "sha256:5378db8a33bf1d48adff3f9efa572d9fb04eaeb36444817cab56f1ba3c595500"}, + {file = "weaviate_client-4.6.7-py3-none-any.whl", hash = "sha256:8793de35264cab33a84fe8cb8c422a257fe4d8334657aaddd8ead853da3fb34a"}, + {file = "weaviate_client-4.6.7.tar.gz", hash = "sha256:202b32e160536f5f44e4a635d30c3d3a0790b1a7ff997f5e243919d1ac5b68a1"}, ] [package.dependencies] @@ -7607,7 +8165,7 @@ grpcio-tools = ">=1.57.0,<2.0.0" httpx = ">=0.25.0,<=0.27.0" pydantic = ">=2.5.0,<3.0.0" requests = ">=2.30.0,<3.0.0" -validators = "0.28.3" +validators = "0.33.0" [[package]] name = "webcolors" @@ -7780,6 +8338,29 @@ files = [ {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, ] +[[package]] +name = "yake" +version = "0.4.8" +description = "Keyword extraction Python package" +optional = false +python-versions = "*" +files = [] +develop = false + +[package.dependencies] +click = ">=6.0" +jellyfish = "*" +networkx = "*" +numpy = "*" +segtok = "*" +tabulate = "*" + +[package.source] +type = "git" +url = "https://github.com/LIAAD/yake" +reference = "HEAD" +resolved_reference = "0fa58cceb465162b6bd0cab7ec967edeb907fbcc" + [[package]] name = "yarl" version = "1.9.4" @@ -7911,4 +8492,4 @@ weaviate = ["weaviate-client"] [metadata] lock-version = "2.0" python-versions = ">=3.9.0,<3.12" -content-hash = "7411f701a2e30a891bf53b215179e343114e95eb5538d45e64fbc46a0ec6b9f0" +content-hash = "9a6ca7d5bd481855d8879b04515d8379b2100bcac8a5c671b46d7c441108e210" diff --git a/pyproject.toml b/pyproject.toml index 64c85b15c..c3da8f979 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "cognee" -version = "0.1.13" +version = "0.1.14" description = "Cognee - is a library for enriching LLM context with a semantic layer for better understanding and reasoning." authors = ["Vasilije Markovic", "Boris Arzentar"] readme = "README.md" @@ -20,14 +20,14 @@ classifiers = [ [tool.poetry.dependencies] python = ">=3.9.0,<3.12" openai = "1.27.0" -pydantic = "^2.5.0" +pydantic = "2.8.2" python-dotenv = "1.0.1" fastapi = "^0.109.2" uvicorn = "0.22.0" boto3 = "^1.26.125" gunicorn = "^20.1.0" sqlalchemy = "^2.0.21" -instructor = "1.2.1" +instructor = "1.3.5" networkx = "^3.2.1" debugpy = "^1.8.0" pyarrow = "15.0.0" @@ -38,16 +38,16 @@ greenlet = "^3.0.3" ruff = "^0.2.2" filetype = "^1.2.0" nltk = "^3.8.1" -dlt = "0.4.12" +dlt = "0.5.1" duckdb = {version = "^0.10.0", extras = ["dlt"]} overrides = "^7.7.0" aiofiles = "^23.2.1" qdrant-client = "^1.9.0" -duckdb-engine = "0.12.1" +duckdb-engine = "0.13.0" graphistry = "^0.33.5" tenacity = "^8.2.3" -weaviate-client = "^4.5.4" -scikit-learn = "^1.4.1.post1" +weaviate-client = "4.6.7" +scikit-learn = "^1.5.0" fastembed = "0.2.7" pypdf = "^4.1.0" neo4j = "5.20.0" @@ -72,6 +72,12 @@ protobuf = "<5.0.0" pydantic-settings = "^2.2.1" anthropic = "^0.26.1" langchain-text-splitters = "^0.2.1" +yake = {git = "https://github.com/LIAAD/yake"} +keybert = "^0.8.5" +pdfplumber = "^0.11.1" +sentry-sdk = {extras = ["fastapi"], version = "^2.9.0"} +langchain-core = '0.2.19' + [tool.poetry.extras]