diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md new file mode 100644 index 00000000..c3d778fb --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -0,0 +1,4 @@ +### Checklist + +- [ ] I have updated the documentation accordingly. +- [ ] I have updated the CHANGELOG.md file accordingly. diff --git a/.github/workflows/semantic_release.yml b/.github/workflows/semantic_release.yml new file mode 100644 index 00000000..4a33bc7d --- /dev/null +++ b/.github/workflows/semantic_release.yml @@ -0,0 +1,67 @@ +name: Semantic Release + +on: + workflow_dispatch: + inputs: + updateType: + description: "version update type" + required: true + type: choice + default: "patch" + options: + - "major" + - "minor" + - "patch" + packageName: + description: "name of the package to update" + required: true + type: choice + options: + - "ragbits" + - "ragbits-cli" + - "ragbits-core" + - "ragbits-document-search" + +jobs: + release: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + steps: + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v2 + with: + version: "0.4.10" + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Create release branch + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git checkout -b release/${{ github.event.inputs.packageName }}-$(date +%Y-%m-%d) + + - name: Update packages + id: packages_update + run: | + echo old_version=`grep version packages/${{ github.event.inputs.packageName }}/pyproject.toml | cut -d \" -f2` >> $GITHUB_OUTPUT + uv run scripts/update_ragbits_package.py ${{ github.event.inputs.packageName }} ${{ github.event.inputs.updateType }} + echo new_version=`grep version packages/${{ github.event.inputs.packageName }}/pyproject.toml | cut -d \" -f2` >> $GITHUB_OUTPUT + uv sync + + - name: Create PR with updated packages + run: | + COMMIT_MESSAGE="release(${{ github.event.inputs.packageName }}): update to v${{ steps.packages_update.outputs.new_version }}" + git add . + git commit -m "$COMMIT_MESSAGE" + git push -u origin HEAD + gh pr create -B main --title "$COMMIT_MESSAGE" \ + --body 'Update ${{ github.event.inputs.packageName }} version from ${{ steps.packages_update.outputs.old_version }} to ${{ steps.packages_update.outputs.new_version }}' + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} diff --git a/.libraries-whitelist.txt b/.libraries-whitelist.txt index 708fc338..eb7e2f65 100644 --- a/.libraries-whitelist.txt +++ b/.libraries-whitelist.txt @@ -1,4 +1,5 @@ pkg_resources tiktoken chardet -chroma-hnswlib \ No newline at end of file +chroma-hnswlib +rouge \ No newline at end of file diff --git a/examples/document-search/chroma.py b/examples/document-search/chroma.py index acd29a7a..734b724e 100644 --- a/examples/document-search/chroma.py +++ b/examples/document-search/chroma.py @@ -11,7 +11,7 @@ from ragbits.core.embeddings import LiteLLMEmbeddings from ragbits.core.vector_store.chromadb_store import ChromaDBStore -from ragbits.document_search import DocumentSearch +from ragbits.document_search import DocumentSearch, SearchConfig from ragbits.document_search.documents.document import DocumentMeta documents = [ @@ -19,6 +19,7 @@ DocumentMeta.create_text_document_from_literal( "Why programmers don't like to swim? Because they're scared of the floating points." ), + DocumentMeta.create_text_document_from_literal("This one is completely unrelated."), ] @@ -37,8 +38,16 @@ async def main(): await document_search.ingest(documents) - results = await document_search.search("I'm boiling my water and I need a joke") - print(results) + print() + print("All documents:") + all_documents = await vector_store.list() + print([doc.metadata["content"] for doc in all_documents]) + + query = "I'm boiling my water and I need a joke" + print() + print(f"Documents similar to: {query}") + results = await document_search.search(query, search_config=SearchConfig(vector_store_kwargs={"k": 2})) + print([element.get_key() for element in results]) if __name__ == "__main__": diff --git a/examples/document-search/from_config.py b/examples/document-search/from_config.py index 89ab7e5b..2253d518 100644 --- a/examples/document-search/from_config.py +++ b/examples/document-search/from_config.py @@ -32,6 +32,18 @@ }, "reranker": {"type": "ragbits.document_search.retrieval.rerankers.noop:NoopReranker"}, "providers": {"txt": {"type": "DummyProvider"}}, + "rephraser": { + "type": "LLMQueryRephraser", + "config": { + "llm": { + "type": "LiteLLM", + "config": { + "model_name": "gpt-4-turbo", + }, + }, + "prompt": "QueryRephraserPrompt", + }, + }, } diff --git a/examples/evaluation/document-search/README.md b/examples/evaluation/document-search/README.md new file mode 100644 index 00000000..4887d642 --- /dev/null +++ b/examples/evaluation/document-search/README.md @@ -0,0 +1,35 @@ +# Document Search Evaluation + +## Ingest + +```sh +uv run ingest.py +``` + +```sh +uv run ingest.py +experiments=chunking-250 +``` + +```sh +uv run ingest.py --multirun +experiments=chunking-250,chunking-500,chunking-1000 +``` + +## Evaluate + +```sh +uv run evaluate.py +``` + +```sh +uv run evaluate.py +experiments=chunking-250 +``` + +```sh +uv run evaluate.py --multirun +experiments=chunking-250,chunking-500,chunking-1000 +``` + +### Log to Neptune + +```sh +uv run evaluate.py neptune.run=True +``` diff --git a/examples/evaluation/document-search/config/data/corpus.yaml b/examples/evaluation/document-search/config/data/corpus.yaml new file mode 100644 index 00000000..8fdf9e07 --- /dev/null +++ b/examples/evaluation/document-search/config/data/corpus.yaml @@ -0,0 +1,4 @@ +name: "hf-docs" +path: "micpst/hf-docs" +split: "train" +num_docs: 5 diff --git a/examples/evaluation/document-search/config/data/qa.yaml b/examples/evaluation/document-search/config/data/qa.yaml new file mode 100644 index 00000000..c58c7b01 --- /dev/null +++ b/examples/evaluation/document-search/config/data/qa.yaml @@ -0,0 +1,3 @@ +name: "hf-docs-retrieval" +path: "micpst/hf-docs-retrieval" +split: "train" diff --git a/examples/evaluation/document-search/config/embedder/litellm.yaml b/examples/evaluation/document-search/config/embedder/litellm.yaml new file mode 100644 index 00000000..114498ac --- /dev/null +++ b/examples/evaluation/document-search/config/embedder/litellm.yaml @@ -0,0 +1,6 @@ +type: LiteLLMEmbeddings +config: + model: "text-embedding-3-small" + options: + dimensions: 768 + encoding_format: float diff --git a/examples/evaluation/document-search/config/experiments/chunking-1000.yaml b/examples/evaluation/document-search/config/experiments/chunking-1000.yaml new file mode 100644 index 00000000..0069a068 --- /dev/null +++ b/examples/evaluation/document-search/config/experiments/chunking-1000.yaml @@ -0,0 +1,20 @@ +# @package _global_ + +task: + name: chunking-1000 + +# used only for ingestion +providers: + txt: + config: + chunking_kwargs: + max_characters: 1000 + md: + config: + chunking_kwargs: + max_characters: 1000 + +# used for both ingestion and evaluation +vector_store: + config: + index_name: chunk-1000 diff --git a/examples/evaluation/document-search/config/experiments/chunking-250.yaml b/examples/evaluation/document-search/config/experiments/chunking-250.yaml new file mode 100644 index 00000000..16ba980f --- /dev/null +++ b/examples/evaluation/document-search/config/experiments/chunking-250.yaml @@ -0,0 +1,20 @@ +# @package _global_ + +task: + name: chunking-250 + +# used only for ingestion +providers: + txt: + config: + chunking_kwargs: + max_characters: 250 + md: + config: + chunking_kwargs: + max_characters: 250 + +# used for both ingestion and evaluation +vector_store: + config: + index_name: chunk-250 diff --git a/examples/evaluation/document-search/config/experiments/chunking-500.yaml b/examples/evaluation/document-search/config/experiments/chunking-500.yaml new file mode 100644 index 00000000..c98a8ea4 --- /dev/null +++ b/examples/evaluation/document-search/config/experiments/chunking-500.yaml @@ -0,0 +1,20 @@ +# @package _global_ + +task: + name: chunking-500 + +# used only for ingestion +providers: + txt: + config: + chunking_kwargs: + max_characters: 500 + md: + config: + chunking_kwargs: + max_characters: 500 + +# used for both ingestion and evaluation +vector_store: + config: + index_name: chunk-500 diff --git a/examples/evaluation/document-search/config/ingestion.yaml b/examples/evaluation/document-search/config/ingestion.yaml new file mode 100644 index 00000000..89ac536d --- /dev/null +++ b/examples/evaluation/document-search/config/ingestion.yaml @@ -0,0 +1,6 @@ +defaults: + - data: corpus + - embedder: litellm + - providers: unstructured + - vector_store: chroma + - _self_ diff --git a/examples/evaluation/document-search/config/providers/unstructured.yaml b/examples/evaluation/document-search/config/providers/unstructured.yaml new file mode 100644 index 00000000..40371198 --- /dev/null +++ b/examples/evaluation/document-search/config/providers/unstructured.yaml @@ -0,0 +1,25 @@ +txt: + type: UnstructuredDefaultProvider + config: + use_api: false + partition_kwargs: + strategy: hi_res + chunking_kwargs: + include_orig_elements: true + max_characters: 1000 + new_after_n_chars: 1000 + overlap: 0 + overlap_all: 0 + +md: + type: UnstructuredDefaultProvider + config: + use_api: false + partition_kwargs: + strategy: hi_res + chunking_kwargs: + include_orig_elements: true + max_characters: 1000 + new_after_n_chars: 1000 + overlap: 0 + overlap_all: 0 diff --git a/examples/evaluation/document-search/config/rephraser/noop.yaml b/examples/evaluation/document-search/config/rephraser/noop.yaml new file mode 100644 index 00000000..8220c3a0 --- /dev/null +++ b/examples/evaluation/document-search/config/rephraser/noop.yaml @@ -0,0 +1 @@ +type: NoopQueryRephraser diff --git a/examples/evaluation/document-search/config/reranker/noop.yaml b/examples/evaluation/document-search/config/reranker/noop.yaml new file mode 100644 index 00000000..8d7a1a38 --- /dev/null +++ b/examples/evaluation/document-search/config/reranker/noop.yaml @@ -0,0 +1 @@ +type: NoopReranker diff --git a/examples/evaluation/document-search/config/retrieval.yaml b/examples/evaluation/document-search/config/retrieval.yaml new file mode 100644 index 00000000..01c270bf --- /dev/null +++ b/examples/evaluation/document-search/config/retrieval.yaml @@ -0,0 +1,26 @@ +defaults: + - data: qa + - embedder: litellm + - providers: unstructured + - vector_store: chroma + - rephraser: noop + - reranker: noop + - _self_ + +task: + name: default + type: document-search + +metrics: + DocumentSearchPrecisionRecallF1: + matching_strategy: RougeChunkMatch + options: + threshold: 0.5 + DocumentSearchRankedRetrievalMetrics: + matching_strategy: RougeChunkMatch + options: + threshold: 0.5 + +neptune: + project: ragbits + run: False diff --git a/examples/evaluation/document-search/config/vector_store/chroma.yaml b/examples/evaluation/document-search/config/vector_store/chroma.yaml new file mode 100644 index 00000000..9090bc2c --- /dev/null +++ b/examples/evaluation/document-search/config/vector_store/chroma.yaml @@ -0,0 +1,9 @@ +type: ChromaDBStore +config: + chroma_client: + type: PersistentClient + config: + path: chroma + embedding_function: + type: ragbits.core.embeddings.litellm:LiteLLMEmbeddings + index_name: default diff --git a/examples/evaluation/document-search/evaluate.py b/examples/evaluation/document-search/evaluate.py new file mode 100644 index 00000000..e25bb9c5 --- /dev/null +++ b/examples/evaluation/document-search/evaluate.py @@ -0,0 +1,67 @@ +# /// script +# requires-python = ">=3.10" +# dependencies = [ +# "ragbits-document-search", +# "ragbits-evaluate[relari]", +# "ragbits[litellm,chromadb]", +# ] +# /// +import asyncio +import logging + +import hydra +from omegaconf import DictConfig + +from ragbits.evaluate.evaluator import Evaluator +from ragbits.evaluate.loaders.hf import HFDataLoader +from ragbits.evaluate.metrics.document_search import document_search_metrics +from ragbits.evaluate.pipelines.document_search import DocumentSearchPipeline +from ragbits.evaluate.utils import log_to_file, log_to_neptune, setup_neptune + +logging.getLogger("LiteLLM").setLevel(logging.ERROR) +logging.getLogger("httpx").setLevel(logging.ERROR) +log = logging.getLogger(__name__) + + +async def bench(config: DictConfig) -> None: + """ + Function running evaluation for all datasets and evaluation tasks defined in hydra config. + + Args: + config: Hydra configuration. + """ + run = setup_neptune(config) + + log.info("Starting evaluation...") + + dataloader = HFDataLoader(config.data) + pipeline = DocumentSearchPipeline(config) + metrics = document_search_metrics(config.metrics) + + evaluator = Evaluator() + results = await evaluator.compute( + pipeline=pipeline, + dataloader=dataloader, + metrics=metrics, + ) + + output_dir = log_to_file(results) + if run: + log_to_neptune(run, results, output_dir) + + log.info("Evaluation results saved under directory: %s", output_dir) + + +@hydra.main(config_path="config", config_name="retrieval", version_base="3.2") +def main(config: DictConfig) -> None: + """ + Function running evaluation for all datasets and evaluation tasks defined in hydra config. + + Args: + config: Hydra configuration. + """ + asyncio.run(bench(config)) + + +if __name__ == "__main__": + main() # pylint: disable=no-value-for-parameter diff --git a/examples/evaluation/document-search/ingest.py b/examples/evaluation/document-search/ingest.py new file mode 100644 index 00000000..4fc9aa76 --- /dev/null +++ b/examples/evaluation/document-search/ingest.py @@ -0,0 +1,66 @@ +# /// script +# requires-python = ">=3.10" +# dependencies = [ +# "ragbits-document-search", +# "ragbits[litellm,chromadb]", +# ] +# /// +import asyncio +import logging + +import hydra +from omegaconf import DictConfig +from tqdm.asyncio import tqdm + +from ragbits.document_search import DocumentSearch +from ragbits.document_search.documents.document import DocumentMeta +from ragbits.document_search.documents.sources import HuggingFaceSource + +logging.getLogger("LiteLLM").setLevel(logging.ERROR) +logging.getLogger("httpx").setLevel(logging.ERROR) +log = logging.getLogger(__name__) + + +async def ingest(config: DictConfig) -> None: + """ + Ingest documents into the document search system. + + Args: + config: Hydra configuration. + """ + log.info("Ingesting documents...") + + document_search = DocumentSearch.from_config(config) # type: ignore + + documents = await tqdm.gather( + *[ + DocumentMeta.from_source( + HuggingFaceSource( + path=config.data.path, + split=config.data.split, + row=i, + ) + ) + for i in range(config.data.num_docs) + ], + desc="Download", + ) + + await document_search.ingest(documents) + + log.info("Ingestion finished.") + + +@hydra.main(config_path="config", config_name="ingestion", version_base="3.2") +def main(config: DictConfig) -> None: + """ + Run the ingestion process. + + Args: + config: Hydra configuration. + """ + asyncio.run(ingest(config)) + + +if __name__ == "__main__": + main() # pylint: disable=no-value-for-parameter diff --git a/packages/ragbits-cli/CHANGELOG.md b/packages/ragbits-cli/CHANGELOG.md new file mode 100644 index 00000000..862a878f --- /dev/null +++ b/packages/ragbits-cli/CHANGELOG.md @@ -0,0 +1,19 @@ +# CHANGELOG + +## Unreleased + +## 0.2.0 (2024-10-23) + +### Changed + +- Improved performance by lazy-loading the modules (#111 #113 #120) +- ragbits-core updated to version v0.2.0 + +## 0.1.0 (2024-10-08) + +### Added + +- Initial release of the package. +- Add prompts lab command. +- Add prompts generate-promptfoo-configs command. + diff --git a/packages/ragbits-cli/pyproject.toml b/packages/ragbits-cli/pyproject.toml index 3950f649..585e603e 100644 --- a/packages/ragbits-cli/pyproject.toml +++ b/packages/ragbits-cli/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "ragbits-cli" -version = "0.1.0" +version = "0.2.0" description = "A CLI application for ragbits - building blocks for rapid development of GenAI applications" readme = "README.md" requires-python = ">=3.10" @@ -30,10 +30,7 @@ classifiers = [ "Topic :: Scientific/Engineering :: Artificial Intelligence", "Topic :: Software Development :: Libraries :: Python Modules", ] -dependencies = [ - "typer>=0.12.5", - "ragbits-core==0.1.0" -] +dependencies = ["typer>=0.12.5", "ragbits-core==0.2.0"] [project.scripts] ragbits = "ragbits.cli:main" diff --git a/packages/ragbits-core/CHANGELOG.md b/packages/ragbits-core/CHANGELOG.md new file mode 100644 index 00000000..4140951e --- /dev/null +++ b/packages/ragbits-core/CHANGELOG.md @@ -0,0 +1,30 @@ +# CHANGELOG + +## Unreleased + +## 0.2.0 (2024-10-23) + +### Added + +- Project README.md (#103). +- Listing entries API for VectorStores (#138). +- Overrides for prompt discovery configurable in `pyproject.toml` file (#101). +- Default LLM factory configurable in `pyproject.toml` file (#101). + +### Changed + +- Fixed bug in chromadb while returning multiple records (#117). +- Fixed bug in prompt rendering for some pydantic models (#137). + +## 0.1.0 (2024-10-08) + +### Added + +- Initial release of the package. +- Introduce core components: Prompts, LLMs, Embeddings and VectorStores. +- `Prompt` class integration with promptfoo. +- LiteLLM integration. +- ChromaDB integration. +- Prompts lab. +- Prompts autodiscovery. + diff --git a/packages/ragbits-core/pyproject.toml b/packages/ragbits-core/pyproject.toml index 2242580f..a531a77d 100644 --- a/packages/ragbits-core/pyproject.toml +++ b/packages/ragbits-core/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "ragbits-core" -version = "0.1.0" +version = "0.2.0" description = "Building blocks for rapid development of GenAI applications" readme = "README.md" requires-python = ">=3.10" @@ -47,7 +47,7 @@ litellm = [ local = [ "torch~=2.2.1", "transformers~=4.44.2", - "numpy~=1.24.0" + "numpy~=1.26.0" ] lab = [ "gradio~=4.44.0", diff --git a/packages/ragbits-core/src/ragbits/core/llms/__init__.py b/packages/ragbits-core/src/ragbits/core/llms/__init__.py index 92a6733d..c28584d9 100644 --- a/packages/ragbits-core/src/ragbits/core/llms/__init__.py +++ b/packages/ragbits-core/src/ragbits/core/llms/__init__.py @@ -1,5 +1,41 @@ +import sys + from .base import LLM from .litellm import LiteLLM from .local import LocalLLM __all__ = ["LLM", "LiteLLM", "LocalLLM"] + + +module = sys.modules[__name__] + + +def get_llm(config: dict) -> LLM: + """ + Initializes and returns an LLM object based on the provided configuration. + + Args: + config : A dictionary containing configuration details for the LLM. + + Returns: + An instance of the specified LLM class, initialized with the provided config + (if any) or default arguments. + + Raises: + KeyError: If the configuration dictionary does not contain a "type" key. + ValueError: If the LLM class is not a subclass of LLM. + """ + llm_type = config["type"] + llm_config = config.get("config", {}) + default_options = llm_config.pop("default_options", None) + + llm_cls = getattr(module, llm_type) + + if not issubclass(llm_cls, LLM): + raise ValueError(f"Invalid LLM class: {llm_cls}") + + # We need to infer the options class from the LLM class. + # pylint: disable=protected-access + options = llm_cls._options_cls(**default_options) if default_options else None # type: ignore + + return llm_cls(**llm_config, default_options=options) diff --git a/packages/ragbits-core/src/ragbits/core/vector_store/__init__.py b/packages/ragbits-core/src/ragbits/core/vector_store/__init__.py index 8d48c78b..1ae7c15c 100644 --- a/packages/ragbits-core/src/ragbits/core/vector_store/__init__.py +++ b/packages/ragbits-core/src/ragbits/core/vector_store/__init__.py @@ -1,11 +1,11 @@ import sys from ..utils.config_handling import get_cls_from_config -from .base import VectorDBEntry, VectorStore +from .base import VectorDBEntry, VectorStore, WhereQuery from .chromadb_store import ChromaDBStore from .in_memory import InMemoryVectorStore -__all__ = ["InMemoryVectorStore", "VectorDBEntry", "VectorStore", "ChromaDBStore"] +__all__ = ["InMemoryVectorStore", "VectorDBEntry", "VectorStore", "ChromaDBStore", "WhereQuery"] module = sys.modules[__name__] diff --git a/packages/ragbits-core/src/ragbits/core/vector_store/base.py b/packages/ragbits-core/src/ragbits/core/vector_store/base.py index 13f657a8..647e7c8f 100644 --- a/packages/ragbits-core/src/ragbits/core/vector_store/base.py +++ b/packages/ragbits-core/src/ragbits/core/vector_store/base.py @@ -1,5 +1,5 @@ import abc -from typing import List, Optional +from typing import Optional from pydantic import BaseModel @@ -16,6 +16,9 @@ class VectorDBEntry(BaseModel): metadata: dict +WhereQuery = dict[str, str | int | float | bool] + + class VectorStore(abc.ABC): """ A class with an implementation of Vector Store, allowing to store and retrieve vectors by similarity function. @@ -27,7 +30,7 @@ def __init__(self, metadata_store: Optional[MetadataStore] = None): self.metadata_store = metadata_store @abc.abstractmethod - async def store(self, entries: List[VectorDBEntry]) -> None: + async def store(self, entries: list[VectorDBEntry]) -> None: """ Store entries in the vector store. @@ -47,3 +50,20 @@ async def retrieve(self, vector: list[float], k: int = 5) -> list[VectorDBEntry] Returns: The entries. """ + + @abc.abstractmethod + async def list( + self, where: WhereQuery | None = None, limit: int | None = None, offset: int = 0 + ) -> list[VectorDBEntry]: + """ + List entries from the vector store. The entries can be filtered, limited and offset. + + Args: + where: The filter dictionary - the keys are the field names and the values are the values to filter by. + Not specifying the key means no filtering. + limit: The maximum number of entries to return. + offset: The number of entries to skip. + + Returns: + The entries. + """ diff --git a/packages/ragbits-core/src/ragbits/core/vector_store/chromadb_store.py b/packages/ragbits-core/src/ragbits/core/vector_store/chromadb_store.py index 1a036998..86f9becb 100644 --- a/packages/ragbits-core/src/ragbits/core/vector_store/chromadb_store.py +++ b/packages/ragbits-core/src/ragbits/core/vector_store/chromadb_store.py @@ -12,7 +12,7 @@ from ragbits.core.embeddings import Embeddings from ragbits.core.metadata_store.base import MetadataStore from ragbits.core.utils.config_handling import get_cls_from_config -from ragbits.core.vector_store import VectorDBEntry, VectorStore +from ragbits.core.vector_store import VectorDBEntry, VectorStore, WhereQuery class ChromaDBStore(VectorStore): @@ -21,9 +21,11 @@ class ChromaDBStore(VectorStore): CHROMA_IDS_KEY = "ids" CHROMA_DOCUMENTS_KEY = "documents" CHROMA_DISTANCES_KEY = "distances" - CHROMA_metadata_KEY = "metadatas" + CHROMA_METADATA_KEY = "metadatas" + CHROMA_EMBEDDINGS_KEY = "embeddings" + CHROMA_INCLUDE_KEYS = [CHROMA_DOCUMENTS_KEY, CHROMA_DISTANCES_KEY, CHROMA_METADATA_KEY, CHROMA_EMBEDDINGS_KEY] DEFAULT_DISTANCE_METHOD = "l2" - METADATA_INNER_KEY = "__key" + METADATA_INNER_KEY = "__metadata" def __init__( self, @@ -171,20 +173,45 @@ async def retrieve(self, vector: List[float], k: int = 5) -> List[VectorDBEntry] The retrieved entries. """ collection = await self._get_chroma_collection() - query_result = collection.query(query_embeddings=[vector], n_results=k) + query_result = collection.query(query_embeddings=[vector], n_results=k, include=self.CHROMA_INCLUDE_KEYS) + return await self._extract_entries_from_query(query_result) + + async def list( + self, where: WhereQuery | None = None, limit: int | None = None, offset: int = 0 + ) -> list[VectorDBEntry]: + """ + List entries from the vector store. The entries can be filtered, limited and offset. + + Args: + where: The filter dictionary - the keys are the field names and the values are the values to filter by. + Not specifying the key means no filtering. + limit: The maximum number of entries to return. + offset: The number of entries to skip. + + Returns: + The entries. + """ + # Cast `where` to chromadb's Where type + where_chroma: chromadb.Where | None = dict(where) if where else None + + collection = await self._get_chroma_collection() + get_results = collection.get(where=where_chroma, limit=limit, offset=offset, include=self.CHROMA_INCLUDE_KEYS) + return await self._extract_entries_from_query(get_results) + + async def _extract_entries_from_query(self, query_results: "chromadb.api.types.QueryResult") -> List[VectorDBEntry]: db_entries: list[VectorDBEntry] = [] - if len(query_result[self.CHROMA_DOCUMENTS_KEY]) < 1: + if len(query_results[self.CHROMA_DOCUMENTS_KEY]) < 1: return db_entries - for i in range(len(query_result[self.CHROMA_DOCUMENTS_KEY][0])): - key = query_result[self.CHROMA_DOCUMENTS_KEY][0][i] + for i in range(len(query_results[self.CHROMA_DOCUMENTS_KEY][0])): + key = query_results[self.CHROMA_DOCUMENTS_KEY][0][i] if self.metadata_store is not None: - metadata = await self.metadata_store.get(query_result[self.CHROMA_IDS_KEY][0][i]) + metadata = await self.metadata_store.get(query_results[self.CHROMA_IDS_KEY][0][i]) else: - metadata = json.loads(query_result[self.CHROMA_metadata_KEY][0][i][self.METADATA_INNER_KEY]) + metadata = json.loads(query_results[self.CHROMA_METADATA_KEY][0][i][self.METADATA_INNER_KEY]) db_entry = VectorDBEntry( key=key, - vector=vector, + vector=query_results[self.CHROMA_EMBEDDINGS_KEY][0][i], metadata=metadata, ) db_entries.append(db_entry) diff --git a/packages/ragbits-core/src/ragbits/core/vector_store/in_memory.py b/packages/ragbits-core/src/ragbits/core/vector_store/in_memory.py index b3cb307f..7105eb7e 100644 --- a/packages/ragbits-core/src/ragbits/core/vector_store/in_memory.py +++ b/packages/ragbits-core/src/ragbits/core/vector_store/in_memory.py @@ -1,9 +1,10 @@ +from itertools import islice from typing import Optional import numpy as np from ragbits.core.metadata_store.base import MetadataStore -from ragbits.core.vector_store.base import VectorDBEntry, VectorStore +from ragbits.core.vector_store.base import VectorDBEntry, VectorStore, WhereQuery class InMemoryVectorStore(VectorStore): @@ -49,3 +50,33 @@ async def retrieve(self, vector: list[float], k: int = 5) -> list[VectorDBEntry] @staticmethod def _calculate_squared_euclidean(vector_x: list[float], vector_b: list[float]) -> float: return np.linalg.norm(np.array(vector_x) - np.array(vector_b)) + + async def list( + self, where: WhereQuery | None = None, limit: int | None = None, offset: int = 0 + ) -> list[VectorDBEntry]: + """ + List entries from the vector store. The entries can be filtered, limited and offset. + + Args: + where: The filter dictionary - the keys are the field names and the values are the values to filter by. + Not specifying the key means no filtering. + limit: The maximum number of entries to return. + offset: The number of entries to skip. + + Returns: + The entries. + """ + entries = iter(self._storage.values()) + + if where: + entries = ( + entry for entry in entries if all(entry.metadata.get(key) == value for key, value in where.items()) + ) + + if offset: + entries = islice(entries, offset, None) + + if limit: + entries = islice(entries, limit) + + return list(entries) diff --git a/packages/ragbits-core/tests/unit/vector_stores/test_chromadb_store.py b/packages/ragbits-core/tests/unit/vector_stores/test_chromadb_store.py index 36d79d3e..618ae9a6 100644 --- a/packages/ragbits-core/tests/unit/vector_stores/test_chromadb_store.py +++ b/packages/ragbits-core/tests/unit/vector_stores/test_chromadb_store.py @@ -109,10 +109,11 @@ async def test_retrieves_entries_correctly(mock_chromadb_store): "metadatas": [ [ { - "__key": '{"content": "test content", "document": {"title": "test title", "source": {"path": "/test/path"}, "document_type": "test_type"}}' + "__metadata": '{"content": "test content", "document": {"title": "test title", "source": {"path": "/test/path"}, "document_type": "test_type"}}' } ] ], + "embeddings": [[[0.12, 0.25, 0.29]]], } entries = await mock_chromadb_store.retrieve(vector) @@ -120,6 +121,35 @@ async def test_retrieves_entries_correctly(mock_chromadb_store): assert len(entries) == 1 assert entries[0].metadata["content"] == "test content" assert entries[0].metadata["document"]["title"] == "test title" + assert entries[0].vector == [0.12, 0.25, 0.29] + + +async def test_lists_entries_correctly(mock_chromadb_store): + mock_collection = await mock_chromadb_store._get_chroma_collection() + mock_collection.get.return_value = { + "documents": [["test content", "test content 2"]], + "metadatas": [ + [ + { + "__metadata": '{"content": "test content", "document": {"title": "test title", "source": {"path": "/test/path"}, "document_type": "test_type"}}', + }, + { + "__metadata": '{"content": "test content 2", "document": {"title": "test title 2", "source": {"path": "/test/path"}, "document_type": "test_type"}}', + }, + ] + ], + "embeddings": [[[0.12, 0.25, 0.29], [0.13, 0.26, 0.30]]], + } + + entries = await mock_chromadb_store.list() + + assert len(entries) == 2 + assert entries[0].metadata["content"] == "test content" + assert entries[0].metadata["document"]["title"] == "test title" + assert entries[0].vector == [0.12, 0.25, 0.29] + assert entries[1].metadata["content"] == "test content 2" + assert entries[1].metadata["document"]["title"] == "test title 2" + assert entries[1].vector == [0.13, 0.26, 0.30] async def test_handles_empty_retrieve(mock_chromadb_store): diff --git a/packages/ragbits-core/tests/unit/vector_stores/test_simple_vector_store.py b/packages/ragbits-core/tests/unit/vector_stores/test_simple_vector_store.py index 8461d93b..6356bef5 100644 --- a/packages/ragbits-core/tests/unit/vector_stores/test_simple_vector_store.py +++ b/packages/ragbits-core/tests/unit/vector_stores/test_simple_vector_store.py @@ -1,28 +1,135 @@ from pathlib import Path +import pytest + from ragbits.core.vector_store.in_memory import InMemoryVectorStore from ragbits.document_search.documents.document import DocumentMeta, DocumentType -from ragbits.document_search.documents.element import TextElement +from ragbits.document_search.documents.element import Element from ragbits.document_search.documents.sources import LocalFileSource -async def test_simple_vector_store(): - store = InMemoryVectorStore() +class AnimalElement(Element): + """ + A test element representing an animal. + """ + + element_type: str = "animal" + name: str + species: str + type: str + age: int + + def get_key(self) -> str: + """ + Get the key of the element which will be used to generate the vector. + + Returns: + The key. + """ + return self.name + +@pytest.fixture(name="store") +async def store_fixture(): document_meta = DocumentMeta(document_type=DocumentType.TXT, source=LocalFileSource(path=Path("test.txt"))) elements = [ - (TextElement(content="dog", document_meta=document_meta), [0.5, 0.5]), - (TextElement(content="cat", document_meta=document_meta), [0.6, 0.6]), + (AnimalElement(name="spikey", species="dog", type="mammal", age=5, document_meta=document_meta), [0.5, 0.5]), + (AnimalElement(name="fluffy", species="cat", type="mammal", age=3, document_meta=document_meta), [0.6, 0.6]), + (AnimalElement(name="slimy", species="frog", type="amphibian", age=1, document_meta=document_meta), [0.7, 0.7]), + (AnimalElement(name="scaly", species="snake", type="reptile", age=2, document_meta=document_meta), [0.8, 0.8]), + (AnimalElement(name="hairy", species="spider", type="insect", age=6, document_meta=document_meta), [0.9, 0.9]), + ( + AnimalElement(name="spotty", species="ladybug", type="insect", age=1, document_meta=document_meta), + [0.1, 0.1], + ), ] entries = [element[0].to_vector_db_entry(vector=element[1]) for element in elements] + store = InMemoryVectorStore() await store.store(entries) + return store + +async def test_simple_vector_store(store): search_vector = [0.4, 0.4] results = await store.retrieve(search_vector, 2) assert len(results) == 2 - assert results[0].metadata["content"] == "dog" - assert results[1].metadata["content"] == "cat" + assert results[0].metadata["name"] == "spikey" + assert results[1].metadata["name"] == "fluffy" + + +async def test_list_all(store): + results = await store.list() + + assert len(results) == 6 + names = [result.metadata["name"] for result in results] + assert names == ["spikey", "fluffy", "slimy", "scaly", "hairy", "spotty"] + + +async def test_list_limit(store): + results = await store.list(limit=3) + + assert len(results) == 3 + names = {result.metadata["name"] for result in results} + assert names == {"spikey", "fluffy", "slimy"} + + +async def test_list_offset(store): + results = await store.list(offset=3) + + assert len(results) == 3 + names = {result.metadata["name"] for result in results} + assert names == {"scaly", "hairy", "spotty"} + + +async def test_limit_with_offset(store): + results = await store.list(limit=2, offset=3) + + assert len(results) == 2 + names = {result.metadata["name"] for result in results} + assert names == {"scaly", "hairy"} + + +async def test_where(store): + results = await store.list(where={"type": "insect"}) + + assert len(results) == 2 + names = {result.metadata["name"] for result in results} + assert names == {"hairy", "spotty"} + + +async def test_multiple_where(store): + results = await store.list(where={"type": "insect", "age": 1}) + + assert len(results) == 1 + assert results[0].metadata["name"] == "spotty" + + +async def test_empty_where(store): + results = await store.list(where={}) + + assert len(results) == 6 + names = {result.metadata["name"] for result in results} + assert names == {"spikey", "fluffy", "slimy", "scaly", "hairy", "spotty"} + + +async def test_empty_results(store): + results = await store.list(where={"type": "bird"}) + + assert len(results) == 0 + + +async def test_empty_results_with_limit(store): + results = await store.list(where={"type": "bird"}, limit=2) + + assert len(results) == 0 + + +async def test_where_limit(store): + results = await store.list(where={"type": "insect"}, limit=1) + + assert len(results) == 1 + assert results[0].metadata["name"] == "hairy" diff --git a/packages/ragbits-document-search/CHANGELOG.md b/packages/ragbits-document-search/CHANGELOG.md new file mode 100644 index 00000000..18c13068 --- /dev/null +++ b/packages/ragbits-document-search/CHANGELOG.md @@ -0,0 +1,26 @@ +# CHANGELOG + +## Unreleased + +## 0.2.0 (2024-10-23) + +### Added + +- Creation of DocumentSearch instances from config (#62). +- Automatic detection of document type (#99). +- LLM-based query rephrasing (#115). +- Batch ingestion from sources (#112). +- Add support to image formats (#121). +- Add HuggingFace sources (#106). + +### Changed + +- ragbits-core updated to version v0.2.0 + +## 0.1.0 (2024-10-08) + +### Added + +- Initial release of the package. +- Introduce core modules: documents, ingestion and retrival. +- Unstructured integration. diff --git a/packages/ragbits-document-search/pyproject.toml b/packages/ragbits-document-search/pyproject.toml index 615ccff1..c28a09c1 100644 --- a/packages/ragbits-document-search/pyproject.toml +++ b/packages/ragbits-document-search/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "ragbits-document-search" -version = "0.1.0" +version = "0.2.0" description = "Document Search module for Ragbits" readme = "README.md" requires-python = ">=3.10" @@ -30,13 +30,7 @@ classifiers = [ "Topic :: Scientific/Engineering :: Artificial Intelligence", "Topic :: Software Development :: Libraries :: Python Modules", ] -dependencies = [ - "numpy~=1.24.0", - "unstructured>=0.15.13", - "unstructured-client>=0.26.0", - "pdf2image>=1.17.0", - "ragbits-core==0.1.0" -] +dependencies = ["unstructured>=0.15.13", "unstructured-client>=0.26.0", "pdf2image>=1.17.0", "ragbits-core==0.2.0"] [project.optional-dependencies] gcs = [ diff --git a/packages/ragbits-document-search/src/ragbits/document_search/__init__.py b/packages/ragbits-document-search/src/ragbits/document_search/__init__.py index aafe8c11..2d5a8d67 100644 --- a/packages/ragbits-document-search/src/ragbits/document_search/__init__.py +++ b/packages/ragbits-document-search/src/ragbits/document_search/__init__.py @@ -1,3 +1,3 @@ -from ._main import DocumentSearch +from ._main import DocumentSearch, SearchConfig -__all__ = ["DocumentSearch"] +__all__ = ["DocumentSearch", "SearchConfig"] diff --git a/packages/ragbits-document-search/src/ragbits/document_search/_main.py b/packages/ragbits-document-search/src/ragbits/document_search/_main.py index 8a72f174..1881c587 100644 --- a/packages/ragbits-document-search/src/ragbits/document_search/_main.py +++ b/packages/ragbits-document-search/src/ragbits/document_search/_main.py @@ -95,7 +95,7 @@ async def search(self, query: str, search_config: SearchConfig = SearchConfig()) Returns: A list of chunks. """ - queries = self.query_rephraser.rephrase(query) + queries = await self.query_rephraser.rephrase(query) elements = [] for rephrased_query in queries: search_vector = await self.embedder.embed_text([rephrased_query]) diff --git a/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/__init__.py b/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/__init__.py index b136d4f3..d26afd20 100644 --- a/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/__init__.py +++ b/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/__init__.py @@ -1,32 +1,44 @@ import sys -from typing import Optional from ragbits.core.utils.config_handling import get_cls_from_config - -from .base import QueryRephraser -from .noop import NoopQueryRephraser - -__all__ = ["NoopQueryRephraser", "QueryRephraser"] +from ragbits.document_search.retrieval.rephrasers.base import QueryRephraser +from ragbits.document_search.retrieval.rephrasers.llm import LLMQueryRephraser +from ragbits.document_search.retrieval.rephrasers.noop import NoopQueryRephraser +from ragbits.document_search.retrieval.rephrasers.prompts import QueryRephraserInput, QueryRephraserPrompt + +__all__ = [ + "get_rephraser", + "QueryRephraser", + "NoopQueryRephraser", + "LLMQueryRephraser", + "QueryRephraserPrompt", + "QueryRephraserInput", +] module = sys.modules[__name__] -def get_rephraser(rephraser_config: Optional[dict]) -> QueryRephraser: +def get_rephraser(config: dict | None = None) -> QueryRephraser: """ Initializes and returns a QueryRephraser object based on the provided configuration. Args: - rephraser_config: A dictionary containing configuration details for the QueryRephraser. + config: A dictionary containing configuration details for the QueryRephraser. Returns: An instance of the specified QueryRephraser class, initialized with the provided config (if any) or default arguments. - """ - if rephraser_config is None: + Raises: + KeyError: If the configuration dictionary does not contain a "type" key. + ValueError: If an invalid rephraser class is specified in the configuration. + """ + if config is None: return NoopQueryRephraser() - rephraser_cls = get_cls_from_config(rephraser_config["type"], module) - config = rephraser_config.get("config", {}) + rephraser_cls = get_cls_from_config(config["type"], module) + + if not issubclass(rephraser_cls, QueryRephraser): + raise ValueError(f"Invalid rephraser class: {rephraser_cls}") - return rephraser_cls(**config) + return rephraser_cls.from_config(config.get("config", {})) diff --git a/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/base.py b/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/base.py index a40b9f9b..3eba3820 100644 --- a/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/base.py +++ b/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/base.py @@ -1,14 +1,13 @@ -import abc +from abc import ABC, abstractmethod -class QueryRephraser(abc.ABC): +class QueryRephraser(ABC): """ Rephrases a query. Can provide multiple rephrased queries from one sentence / question. """ - @staticmethod - @abc.abstractmethod - def rephrase(query: str) -> list[str]: + @abstractmethod + async def rephrase(self, query: str) -> list[str]: """ Rephrase a query. @@ -18,3 +17,16 @@ def rephrase(query: str) -> list[str]: Returns: The rephrased queries. """ + + @classmethod + def from_config(cls, config: dict) -> "QueryRephraser": + """ + Create an instance of `QueryRephraser` from a configuration dictionary. + + Args: + config: A dictionary containing configuration settings for the rephraser. + + Returns: + An instance of the rephraser class initialized with the provided configuration. + """ + return cls(**config) diff --git a/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/llm.py b/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/llm.py new file mode 100644 index 00000000..8398b2a5 --- /dev/null +++ b/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/llm.py @@ -0,0 +1,67 @@ +from typing import Any + +from ragbits.core.llms import get_llm +from ragbits.core.llms.base import LLM +from ragbits.core.prompt import Prompt +from ragbits.document_search.retrieval.rephrasers.base import QueryRephraser +from ragbits.document_search.retrieval.rephrasers.prompts import ( + QueryRephraserInput, + QueryRephraserPrompt, + get_rephraser_prompt, +) + + +class LLMQueryRephraser(QueryRephraser): + """ + A rephraser class that uses a LLM to rephrase queries. + """ + + def __init__(self, llm: LLM, prompt: type[Prompt[QueryRephraserInput, Any]] | None = None): + """ + Initialize the LLMQueryRephraser with a LLM. + + Args: + llm: A LLM instance to handle query rephrasing. + prompt: The prompt to use for rephrasing queries. + """ + self._llm = llm + self._prompt = prompt or QueryRephraserPrompt + + async def rephrase(self, query: str) -> list[str]: + """ + Rephrase a given query using the LLM. + + Args: + query: The query to be rephrased. If not provided, a custom prompt must be given. + + Returns: + A list containing the rephrased query. + + Raises: + LLMConnectionError: If there is a connection error with the LLM API. + LLMStatusError: If the LLM API returns an error status code. + LLMResponseError: If the LLM API response is invalid. + """ + input_data = self._prompt.input_type(query=query) # type: ignore + prompt = self._prompt(input_data) + response = await self._llm.generate(prompt) + return response if isinstance(response, list) else [response] + + @classmethod + def from_config(cls, config: dict) -> "LLMQueryRephraser": + """ + Create an instance of `LLMQueryRephraser` from a configuration dictionary. + + Args: + config: A dictionary containing configuration settings for the rephraser. + + Returns: + An instance of the rephraser class initialized with the provided configuration. + + Raises: + KeyError: If the configuration dictionary does not contain the required keys. + ValueError: If the prompt class is not a subclass of `Prompt` or the LLM class is not a subclass of `LLM`. + """ + llm = get_llm(config["llm"]) + prompt_cls = get_rephraser_prompt(prompt) if (prompt := config.get("prompt")) else None + return cls(llm=llm, prompt=prompt_cls) diff --git a/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/noop.py b/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/noop.py index 8e6b92fd..b48bd7de 100644 --- a/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/noop.py +++ b/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/noop.py @@ -6,8 +6,7 @@ class NoopQueryRephraser(QueryRephraser): A no-op query paraphraser that does not change the query. """ - @staticmethod - def rephrase(query: str) -> list[str]: + async def rephrase(self, query: str) -> list[str]: """ Mock implementation which outputs the same query as in input. diff --git a/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/prompts.py b/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/prompts.py new file mode 100644 index 00000000..1f1e0c90 --- /dev/null +++ b/packages/ragbits-document-search/src/ragbits/document_search/retrieval/rephrasers/prompts.py @@ -0,0 +1,54 @@ +import sys +from typing import Any + +from pydantic import BaseModel + +from ragbits.core.prompt.prompt import Prompt +from ragbits.core.utils.config_handling import get_cls_from_config + +module = sys.modules[__name__] + + +class QueryRephraserInput(BaseModel): + """ + Input data for the query rephraser prompt. + """ + + query: str + + +class QueryRephraserPrompt(Prompt[QueryRephraserInput, str]): + """ + A prompt class for generating a rephrased version of a user's query using a LLM. + """ + + user_prompt = "{{ query }}" + system_prompt = ( + "You are an expert in query rephrasing and clarity improvement. " + "Your task is to return a single paraphrased version of a user's query, " + "correcting any typos, handling abbreviations and improving clarity. " + "Focus on making the query more precise and readable while keeping its original intent.\n\n" + "Just return the rephrased query. No additional explanations are needed." + ) + + +def get_rephraser_prompt(prompt: str) -> type[Prompt[QueryRephraserInput, Any]]: + """ + Initializes and returns a QueryRephraser object based on the provided configuration. + + Args: + prompt: The prompt class to use for rephrasing queries. + + Returns: + An instance of the specified QueryRephraser class, initialized with the provided config + (if any) or default arguments. + + Raises: + ValueError: If the prompt class is not a subclass of `Prompt`. + """ + prompt_cls = get_cls_from_config(prompt, module) + + if not issubclass(prompt_cls, Prompt): + raise ValueError(f"Invalid rephraser prompt class: {prompt_cls}") + + return prompt_cls diff --git a/packages/ragbits-evaluate/CHANGELOG.md b/packages/ragbits-evaluate/CHANGELOG.md new file mode 100644 index 00000000..8d112be7 --- /dev/null +++ b/packages/ragbits-evaluate/CHANGELOG.md @@ -0,0 +1,13 @@ +# CHANGELOG + +## Unreleased + +## 0.2.0 (2024-10-23) + +- Initial release of the package. +- Evaluation pipeline framework with capability to define evaluators & metrics. +- Evaluation pipeline for `ragbits-document-search`. + +### Changed + +- ragbits-core updated to version v0.2.0 diff --git a/packages/ragbits-evaluate/README.md b/packages/ragbits-evaluate/README.md new file mode 100644 index 00000000..37cc4f7c --- /dev/null +++ b/packages/ragbits-evaluate/README.md @@ -0,0 +1 @@ +# Ragbits Evaluate diff --git a/packages/ragbits-evaluate/pyproject.toml b/packages/ragbits-evaluate/pyproject.toml new file mode 100644 index 00000000..549d8075 --- /dev/null +++ b/packages/ragbits-evaluate/pyproject.toml @@ -0,0 +1,60 @@ +[project] +name = "ragbits-evaluate" +version = "0.2.0" +description = "Evaluation module for Ragbits components" +readme = "README.md" +requires-python = ">=3.10" +license = "MIT" +authors = [ + { name = "deepsense.ai", email = "ragbits@deepsense.ai"} +] +keywords = [ + "Retrieval Augmented Generation", + "RAG", + "Large Language Models", + "LLMs", + "Generative AI", + "GenAI", + "Evaluation" +] +classifiers = [ + "Development Status :: 4 - Beta", + "Environment :: Console", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Scientific/Engineering :: Artificial Intelligence", + "Topic :: Software Development :: Libraries :: Python Modules", +] +dependencies = ["hydra-core~=1.3.2", "neptune~=1.12.0", "ragbits-core==0.2.0"] + +[project.optional-dependencies] +relari = [ + "continuous-eval~=0.3.12", +] + +[tool.uv] +dev-dependencies = [ + "pre-commit~=3.8.0", + "pytest~=8.3.3", + "pytest-cov~=5.0.0", + "pytest-asyncio~=0.24.0", + "pip-licenses>=4.0.0,<5.0.0" +] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.build.targets.wheel] +packages = ["src/ragbits"] + +[tool.pytest.ini_options] +asyncio_mode = "auto" diff --git a/packages/ragbits-evaluate/src/ragbits/evaluate/__init__.py b/packages/ragbits-evaluate/src/ragbits/evaluate/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/ragbits-evaluate/src/ragbits/evaluate/evaluator.py b/packages/ragbits-evaluate/src/ragbits/evaluate/evaluator.py new file mode 100644 index 00000000..b57d6f7f --- /dev/null +++ b/packages/ragbits-evaluate/src/ragbits/evaluate/evaluator.py @@ -0,0 +1,112 @@ +import time +from dataclasses import asdict +from typing import Any, Iterable + +from tqdm.asyncio import tqdm + +from ragbits.evaluate.loaders.base import DataLoader +from ragbits.evaluate.metrics.base import MetricSet +from ragbits.evaluate.pipelines.base import EvaluationPipeline, EvaluationResult + + +class Evaluator: + """ + Evaluator class. + """ + + async def compute( + self, + pipeline: EvaluationPipeline, + dataloader: DataLoader, + metrics: MetricSet, + ) -> dict[str, Any]: + """ + Compute the evaluation results for the given pipeline and data. + + Args: + pipeline: The pipeline to be evaluated. + dataloader: The dataloader to load the data. + metrics: The metrics to be computed. + + Returns: + The evaluation results. + """ + dataset = await dataloader.load() + results, perf_results = await self._call_pipeline(pipeline, dataset) + computed_metrics = self._compute_metrics(metrics, results) + processed_results = self._results_processor(results) + + return { + **perf_results, + **computed_metrics, + **processed_results, + } + + async def _call_pipeline( + self, + pipeline: EvaluationPipeline, + dataset: Iterable, + ) -> tuple[list[EvaluationResult], dict[str, Any]]: + """ + Call the pipeline with the given data. + + Args: + pipeline: The pipeline to be called. + data: The evaluation data. + + Returns: + The evaluation results and performance metrics. + """ + start_time = time.perf_counter() + pipe_outputs = await tqdm.gather(*[pipeline(data) for data in dataset], desc="Evaluation") + end_time = time.perf_counter() + return pipe_outputs, self._compute_time_perf(start_time, end_time, len(pipe_outputs)) + + def _results_processor(self, results: list[EvaluationResult]) -> dict[str, Any]: + """ + Process the results. + + Args: + results: The evaluation results. + + Returns: + The processed results. + """ + return {"results": [asdict(result) for result in results]} + + def _compute_metrics(self, metrics: MetricSet, results: list[EvaluationResult]) -> dict[str, Any]: + """ + Compute a metric using the given inputs. + + Args: + metrics: The metrics to be computed. + results: The evaluation results. + + Returns: + The computed metric. + """ + return {"metrics": metrics.compute(results)} + + def _compute_time_perf(self, start_time: float, end_time: float, num_samples: int) -> dict[str, Any]: + """ + Compute the performance metrics. + + Args: + start_time: The start time. + end_time: The end time. + num_samples: The number of samples. + + Returns: + The performance metrics. + """ + latency = end_time - start_time + throughput = num_samples / latency + latency_sample = 1.0 / throughput if throughput > 0 else 0.0 + + return { + "time_perf": { + "total_time_in_seconds": latency, + "samples_per_second": throughput, + "latency_in_seconds": latency_sample, + }, + } diff --git a/packages/ragbits-evaluate/src/ragbits/evaluate/loaders/__init__.py b/packages/ragbits-evaluate/src/ragbits/evaluate/loaders/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/ragbits-evaluate/src/ragbits/evaluate/loaders/base.py b/packages/ragbits-evaluate/src/ragbits/evaluate/loaders/base.py new file mode 100644 index 00000000..d8407095 --- /dev/null +++ b/packages/ragbits-evaluate/src/ragbits/evaluate/loaders/base.py @@ -0,0 +1,24 @@ +from abc import ABC, abstractmethod +from typing import Generic, TypeVar + +from omegaconf import DictConfig + +DataT = TypeVar("DataT") + + +class DataLoader(Generic[DataT], ABC): + """ + Data loader. + """ + + def __init__(self, config: DictConfig) -> None: + self.config = config + + @abstractmethod + async def load(self) -> DataT: + """ + Load the data. + + Returns: + The loaded data. + """ diff --git a/packages/ragbits-evaluate/src/ragbits/evaluate/loaders/hf.py b/packages/ragbits-evaluate/src/ragbits/evaluate/loaders/hf.py new file mode 100644 index 00000000..35226637 --- /dev/null +++ b/packages/ragbits-evaluate/src/ragbits/evaluate/loaders/hf.py @@ -0,0 +1,25 @@ +from typing import TypeAlias + +from datasets import Dataset, DatasetDict, IterableDataset, IterableDatasetDict, load_dataset + +from ragbits.evaluate.loaders.base import DataLoader + +HFData: TypeAlias = DatasetDict | Dataset | IterableDatasetDict | IterableDataset + + +class HFDataLoader(DataLoader[HFData]): + """ + Hugging Face data loader. + """ + + async def load(self) -> HFData: + """ + Load the data from Hugging Face. + + Returns: + The loaded data. + """ + return load_dataset( + path=self.config.path, + split=self.config.split, + ) diff --git a/packages/ragbits-evaluate/src/ragbits/evaluate/metrics/__init__.py b/packages/ragbits-evaluate/src/ragbits/evaluate/metrics/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/ragbits-evaluate/src/ragbits/evaluate/metrics/base.py b/packages/ragbits-evaluate/src/ragbits/evaluate/metrics/base.py new file mode 100644 index 00000000..c168c708 --- /dev/null +++ b/packages/ragbits-evaluate/src/ragbits/evaluate/metrics/base.py @@ -0,0 +1,78 @@ +from abc import ABC, abstractmethod +from typing import Any, Generic, Optional, TypeVar + +from omegaconf import DictConfig +from typing_extensions import Self + +from ragbits.evaluate.pipelines.base import EvaluationResult + +ResultT = TypeVar("ResultT", bound=EvaluationResult) + + +class Metric(Generic[ResultT], ABC): + """ + Base class for metrics. + """ + + def __init__(self, config: Optional[DictConfig] = None) -> None: + """ + Initializes the metric. + + Args: + config: The metric configuration. + """ + super().__init__() + self.config = getattr(config, self.__class__.__name__, DictConfig({})) + + @abstractmethod + def compute(self, results: list[ResultT]) -> dict[str, Any]: + """ + Compute the metric. + + Args: + results: The evaluation results. + + Returns: + The computed metric. + """ + + +class MetricSet(Generic[ResultT]): + """ + Represents a set of metrics. + """ + + def __init__(self, *metrics: type[Metric[ResultT]]) -> None: + """ + Initializes the metric set. + + Args: + metrics: The metrics. + """ + self._metrics = metrics + self.metrics: list[Metric[ResultT]] = [] + + def __call__(self, config: Optional[DictConfig] = None) -> Self: + """ + Initializes the metrics. + + Args: + config: The configuration for the metrics. + + Returns: + The initialized metric set. + """ + self.metrics = [metric(config) for metric in self._metrics] + return self + + def compute(self, results: list[ResultT]) -> dict[str, Any]: + """ + Compute the metrics. + + Args: + results: The evaluation results. + + Returns: + The computed metrics. + """ + return {name: value for metric in self.metrics for name, value in metric.compute(results).items()} diff --git a/packages/ragbits-evaluate/src/ragbits/evaluate/metrics/document_search.py b/packages/ragbits-evaluate/src/ragbits/evaluate/metrics/document_search.py new file mode 100644 index 00000000..132e9b6a --- /dev/null +++ b/packages/ragbits-evaluate/src/ragbits/evaluate/metrics/document_search.py @@ -0,0 +1,68 @@ +import importlib +from abc import ABC +from typing import Any, Optional + +from continuous_eval.metrics.retrieval import PrecisionRecallF1, RankedRetrievalMetrics +from omegaconf import DictConfig + +from ragbits.evaluate.metrics.base import Metric, MetricSet +from ragbits.evaluate.pipelines.document_search import DocumentSearchResult + + +class DocumentSearchMetric(Metric[DocumentSearchResult], ABC): + """ + Metric for document search evaluation based on Relari backend. + More details can be found [here](https://docs.relari.ai/category/retrieval-rag). + """ + + metric_cls: type[PrecisionRecallF1 | RankedRetrievalMetrics] + + def __init__(self, config: Optional[DictConfig] = None) -> None: + """ + Initializes the metric. + + Args: + config: The metric configuration. + """ + super().__init__(config) + + matching_strategy = getattr( + importlib.import_module("continuous_eval.metrics.retrieval.matching_strategy"), + self.config.matching_strategy, + ) + self.metric = self.metric_cls(matching_strategy(**self.config.options)) + + def compute(self, results: list[DocumentSearchResult]) -> dict[str, Any]: + """ + Compute the metric. + + Args: + results: The evaluation results. + + Returns: + The computed metric. + """ + return self.metric.aggregate( + [self.metric(result.predicted_passages, result.reference_passages) for result in results] + ) + + +class DocumentSearchPrecisionRecallF1(DocumentSearchMetric): + """ + Precision, recall, and F1 score for context retrieval. + More details can be found [here](https://docs.relari.ai/metrics/Retrieval/Deterministic/precision_recall). + """ + + metric_cls = PrecisionRecallF1 + + +class DocumentSearchRankedRetrievalMetrics(DocumentSearchMetric): + """ + Rank-aware metrics takes into account the order in which the contexts are retrieved. + More details can be found [here](https://docs.relari.ai/metrics/Retrieval/Deterministic/rank_aware_metrics). + """ + + metric_cls = RankedRetrievalMetrics + + +document_search_metrics = MetricSet(DocumentSearchPrecisionRecallF1, DocumentSearchRankedRetrievalMetrics) diff --git a/packages/ragbits-evaluate/src/ragbits/evaluate/pipelines/__init__.py b/packages/ragbits-evaluate/src/ragbits/evaluate/pipelines/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/ragbits-evaluate/src/ragbits/evaluate/pipelines/base.py b/packages/ragbits-evaluate/src/ragbits/evaluate/pipelines/base.py new file mode 100644 index 00000000..d435b05d --- /dev/null +++ b/packages/ragbits-evaluate/src/ragbits/evaluate/pipelines/base.py @@ -0,0 +1,40 @@ +from abc import ABC, abstractmethod +from dataclasses import dataclass +from typing import Any, Optional + +from omegaconf import DictConfig + + +@dataclass +class EvaluationResult(ABC): + """ + Represents the result of a single evaluation. + """ + + +class EvaluationPipeline(ABC): + """ + Collection evaluation pipeline. + """ + + def __init__(self, config: Optional[DictConfig] = None) -> None: + """ + Initializes the evaluation pipeline. + + Args: + config: The evaluation pipeline configuration. + """ + super().__init__() + self.config = config or DictConfig({}) + + @abstractmethod + async def __call__(self, data: dict[str, Any]) -> EvaluationResult: + """ + Runs the evaluation pipeline. + + Args: + data: The evaluation data. + + Returns: + The evaluation result. + """ diff --git a/packages/ragbits-evaluate/src/ragbits/evaluate/pipelines/document_search.py b/packages/ragbits-evaluate/src/ragbits/evaluate/pipelines/document_search.py new file mode 100644 index 00000000..c25954ce --- /dev/null +++ b/packages/ragbits-evaluate/src/ragbits/evaluate/pipelines/document_search.py @@ -0,0 +1,51 @@ +from dataclasses import dataclass +from functools import cached_property + +from ragbits.document_search import DocumentSearch +from ragbits.document_search.documents.element import TextElement +from ragbits.evaluate.pipelines.base import EvaluationPipeline, EvaluationResult + + +@dataclass +class DocumentSearchResult(EvaluationResult): + """ + Represents the result of a single evaluation. + """ + + question: str + reference_passages: list[str] + predicted_passages: list[str] + + +class DocumentSearchPipeline(EvaluationPipeline): + """ + Document search evaluation pipeline. + """ + + @cached_property + def document_search(self) -> "DocumentSearch": + """ + Returns the document search instance. + + Returns: + The document search instance. + """ + return DocumentSearch.from_config(self.config) # type: ignore + + async def __call__(self, data: dict) -> DocumentSearchResult: + """ + Runs the document search evaluation pipeline. + + Args: + data: The evaluation data. + + Returns: + The evaluation result. + """ + elements = await self.document_search.search(data["question"]) + predicted_passages = [element.content for element in elements if isinstance(element, TextElement)] + return DocumentSearchResult( + question=data["question"], + reference_passages=data["passages"], + predicted_passages=predicted_passages, + ) diff --git a/packages/ragbits-evaluate/src/ragbits/evaluate/utils.py b/packages/ragbits-evaluate/src/ragbits/evaluate/utils.py new file mode 100644 index 00000000..917418ce --- /dev/null +++ b/packages/ragbits-evaluate/src/ragbits/evaluate/utils.py @@ -0,0 +1,91 @@ +import json +import sys +from datetime import datetime +from pathlib import Path +from typing import Any + +from hydra.core.hydra_config import HydraConfig +from neptune import Run +from neptune.utils import stringify_unsupported +from omegaconf import DictConfig + + +def _save(file_path: Path, **data: Any) -> None: + """ + Save the data to a file. Add the current timestamp and Python version to the data. + + Args: + file_path: The path to the file. + data: The data to be saved. + """ + current_time = datetime.now() + + data["_timestamp"] = current_time.isoformat() + data["_python_version"] = sys.version + data["_interpreter_path"] = sys.executable + + with open(file_path, "w", encoding="utf-8") as file: + json.dump(data, file, indent=4) + + +def log_to_file(results: dict[str, Any], output_dir: Path | None = None) -> Path: + """ + Log the evaluation results locally. + + Args: + results: The evaluation results. + output_dir: The output directory. + + Returns: + The output directory. + """ + output_dir = output_dir or Path(HydraConfig.get().runtime.output_dir) + metrics_file = output_dir / "metrics.json" + results_file = output_dir / "results.json" + + _save(metrics_file, metrics=results["metrics"], time_perf=results["time_perf"]) + _save(results_file, results=results["results"]) + + return output_dir + + +def setup_neptune(config: DictConfig) -> Run | None: + """ + Setup the Neptune run. + + Args: + config: The Hydra configuration. + + Returns: + The Neptune run. + """ + if config.neptune.run: + run = Run( + project=config.neptune.project, + tags=[ + config.task.type, + config.task.name, + config.data.name, + ], + ) + run["config"] = stringify_unsupported(config) + return run + return None + + +def log_to_neptune(run: Run, results: dict[str, Any], output_dir: Path | None = None) -> None: + """ + Log the evaluation results to Neptune. + + Args: + run: The Neptune run. + results: The evaluation results. + output_dir: The output directory. + """ + output_dir = output_dir or Path(HydraConfig.get().runtime.output_dir) + + run["evaluation/metrics"] = stringify_unsupported(results["metrics"]) + run["evaluation/time_perf"] = stringify_unsupported(results["time_perf"]) + run["evaluation/results"] = stringify_unsupported(results["results"]) + run["evaluation/metrics.json"].upload((output_dir / "metrics.json").as_posix()) + run["evaluation/results.json"].upload((output_dir / "results.json").as_posix()) diff --git a/packages/ragbits/CHANGELOG.md b/packages/ragbits/CHANGELOG.md new file mode 100644 index 00000000..965a24d9 --- /dev/null +++ b/packages/ragbits/CHANGELOG.md @@ -0,0 +1,54 @@ +# CHANGELOG + +## Unreleased + +## 0.2.0 (2024-10-23) + +### Added + +- ragbits-evaluate v0.2.0: + - Initial release of the package (#91). + - Evaluation pipeline framework with capability to define evaluators & metrics. + - Evaluation pipeline for `ragbits-document-search`. + +### Changed + +- ragbits-cli updated to version v0.2.0 + - Improved performance by lazy-loading the modules (#111 #113 #120) +- ragbits-document-search updated to version v0.2.0 + - Creation of DocumentSearch instances from config (#62). + - Automatic detection of document type (#99). + - LLM-based query rephrasing (#115). + - Batch ingestion from sources (#112). + - Support to image formats (#121). + - HuggingFace sources (#106). +- ragbits-core updated to version v0.2.0 + - Project README.md (#103). + - Listing entries API for VectorStores (#138). + - Overrides for prompt discovery configurable in `pyproject.toml` file (#101). + - Default LLM factory configurable in `pyproject.toml` file (#101). + - Fixed bug in chromadb while returning multiple records (#117). + - Fixed bug in prompt rendering for some pydantic models (#137). + +## 0.1.0 (2024-10-08) + +### Added + +- ragbits-core v0.1.0: + - Initial release of the package. + - Introduce core components: Prompts, LLMs, Embeddings and VectorStores. + - `Prompt` class integration with promptfoo. + - LiteLLM integration. + - ChromaDB integration. + - Prompts lab. + - Prompts autodiscovery. + +- ragbits-cli v0.1.0: + - Initial release of the package. + - Add prompts lab command. + - Add prompts generate-promptfoo-configs command. + +- ragbits-document-search v0.1.0: + - Initial release of the package. + - Introduce core modules: documents, ingestion and retrival. + - Unstructured integration. diff --git a/packages/ragbits/pyproject.toml b/packages/ragbits/pyproject.toml index d2dd7ab7..4c4fda72 100644 --- a/packages/ragbits/pyproject.toml +++ b/packages/ragbits/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "ragbits" -version = "0.1.0" +version = "0.2.0" description = "Building blocks for rapid development of GenAI applications" readme = "README.md" requires-python = ">=3.10" @@ -31,9 +31,10 @@ classifiers = [ "Topic :: Software Development :: Libraries :: Python Modules", ] dependencies = [ - "ragbits-document-search==0.1.0", - "ragbits-cli==0.1.0", - "ragbits-core==0.1.0" + "ragbits-document-search==0.2.0", + "ragbits-cli==0.2.0", + "ragbits-evaluate==0.2.0", + "ragbits-core==0.2.0" ] [build-system] diff --git a/pyproject.toml b/pyproject.toml index 112ea2bc..cabaf4fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,12 +5,12 @@ description = "Ragbits development workspace" readme = "README.md" requires-python = ">=3.10" dependencies = [ + "ragbits-cli", "ragbits-core[litellm,local,lab,chromadb]", "ragbits-document-search[gcs, huggingface]", - "ragbits-cli" + "ragbits-evaluate[relari]", ] - [tool.uv] dev-dependencies = [ "pre-commit~=3.8.0", @@ -29,15 +29,17 @@ dev-dependencies = [ ] [tool.uv.sources] +ragbits-cli = { workspace = true } ragbits-core = { workspace = true } ragbits-document-search = { workspace = true } -ragbits-cli = { workspace = true } +ragbits-evaluate = {workspace = true} [tool.uv.workspace] members = [ + "packages/ragbits-cli", "packages/ragbits-core", "packages/ragbits-document-search", - "packages/ragbits-cli" + "packages/ragbits-evaluate", ] [tool.isort] @@ -125,9 +127,10 @@ check_untyped_defs = true no_implicit_optional = true explicit_package_bases = true mypy_path = [ - 'packages/ragbits-core/src', - 'packages/ragbits-document-search/src', - 'packages/ragbits-cli/src', + "packages/ragbits-cli/src", + "packages/ragbits-core/src", + "packages/ragbits-document-search/src", + "packages/ragbits-evaluate/src", ] [[tool.mypy.overrides]] diff --git a/scripts/update_ragbits_package.py b/scripts/update_ragbits_package.py index b78f4235..98177dc6 100644 --- a/scripts/update_ragbits_package.py +++ b/scripts/update_ragbits_package.py @@ -12,8 +12,9 @@ # # uv run scripts/update_ragbits_package.py # - +import re from copy import deepcopy +from datetime import datetime from enum import Enum from pathlib import Path from typing import Optional @@ -46,7 +47,7 @@ def _version_to_list(version_string): return [int(part) for part in version_string.split(".")] -def _check_update_type(version: str, new_version: str) -> Optional[UpdateType]: +def _check_update_type(version: str, new_version: str) -> UpdateType: version_list = _version_to_list(version) new_version_list = _version_to_list(new_version) @@ -54,9 +55,7 @@ def _check_update_type(version: str, new_version: str) -> Optional[UpdateType]: return UpdateType.MAJOR if version_list[1] != new_version_list[1]: return UpdateType.MINOR - if version_list[2] != new_version_list[2]: - return UpdateType.PATCH - return None + return UpdateType.PATCH def _get_updated_version(version: str, update_type: UpdateType) -> str: @@ -78,6 +77,7 @@ def _update_pkg_version( pkg_pyproject: Optional[tomlkit.TOMLDocument] = None, new_version: Optional[str] = None, update_type: Optional[UpdateType] = None, + sync_ragbits_version: bool = False, ) -> tuple[str, str]: if not pkg_pyproject: pkg_pyproject = tomlkit.parse((PACKAGES_DIR / pkg_name / "pyproject.toml").read_text()) @@ -97,9 +97,87 @@ def _update_pkg_version( assert isinstance(new_version, str) pprint(f"[green]The {pkg_name} package was successfully updated from {version} to {new_version}.[/green]") + if pkg_name != "ragbits": + _sync_ragbits_deps(pkg_name, version, new_version, sync_ragbits_version) + + _create_changelog_release(pkg_name=pkg_name, new_version=new_version) + return version, new_version +def _sync_ragbits_deps(pkg_name: str, pkg_version: str, pkg_new_version: str, update_version: bool = True): + ragbits_pkg_project = tomlkit.parse((PACKAGES_DIR / "ragbits" / "pyproject.toml").read_text()) + ragbits_deps: list[str] = [dep.split("==")[0] for dep in ragbits_pkg_project["project"]["dependencies"]] + + update_type = _check_update_type(pkg_version, pkg_new_version) + + if pkg_name in ragbits_deps: + idx = ragbits_pkg_project["project"]["dependencies"].index(f"{pkg_name}=={pkg_version}") + del ragbits_pkg_project["project"]["dependencies"][idx] + ragbits_pkg_project["project"]["dependencies"].insert(idx, f"{pkg_name}=={pkg_new_version}") + _add_updated_dependency_to_changelog("ragbits", pkg_name, pkg_new_version) + + if update_version: + ragbits_old_version = ragbits_pkg_project["project"]["version"] + ragbits_new_version = _get_updated_version(ragbits_old_version, update_type=update_type) + ragbits_pkg_project["project"]["version"] = ragbits_new_version + + pprint( + "[green]The ragbits package was successfully updated " + f"from {ragbits_old_version} to {ragbits_new_version}.[/green]" + ) + _create_changelog_release(pkg_name="ragbits", new_version=ragbits_new_version) + + (PACKAGES_DIR / "ragbits" / "pyproject.toml").write_text(tomlkit.dumps(ragbits_pkg_project)) + + +def _add_updated_dependency_to_changelog(pkg_name: str, dependency_name: str, new_dependency_version: str) -> None: + changelog_path = PACKAGES_DIR / pkg_name / "CHANGELOG.md" + changelog_content = changelog_path.read_text() + + # Find the "## Unreleased" section + unreleased_match = re.search(r"^## Unreleased\s*$", changelog_content, re.MULTILINE) + if unreleased_match: + unreleased_index = unreleased_match.end() + + # Find the next section after "## Unreleased" + next_section_match = re.search(r"^##\s", changelog_content[unreleased_index:], re.MULTILINE) + next_section_index = ( + unreleased_index + next_section_match.start() if next_section_match else len(changelog_content) + ) + + # Check if "### Changed" exists in the "## Unreleased" section + changed_match = re.search( + r"^### Changed\s*$", changelog_content[unreleased_index:next_section_index], re.MULTILINE + ) + if not changed_match: + # If "### Changed" does not exist, create it above any existing sections + changelog_content = ( + changelog_content[:unreleased_index] + + f"\n### Changed\n\n- {dependency_name} updated to version v{new_dependency_version}\n" + + changelog_content[unreleased_index:] + ) + else: + # If "### Changed" exists, append the new entry + changed_index = unreleased_index + changed_match.end() + changelog_content = ( + changelog_content[:changed_index] + + f"\n- {dependency_name} updated to version v{new_dependency_version}" + + changelog_content[changed_index:] + ) + + changelog_path.write_text(changelog_content) + + +def _create_changelog_release(pkg_name: str, new_version: str) -> None: + changelog_path = PACKAGES_DIR / pkg_name / "CHANGELOG.md" + changelog_content = changelog_path.read_text() + changelog_content = changelog_content.replace( + "## Unreleased", f"## Unreleased\n\n## {new_version} ({datetime.today().strftime('%Y-%m-%d')})" + ) + changelog_path.write_text(changelog_content) + + def run(pkg_name: Optional[str] = typer.Argument(None), update_type: Optional[str] = typer.Argument(None)) -> None: """ Main entry point for the package version updater. Updates package versions based on user input. @@ -130,10 +208,12 @@ def run(pkg_name: Optional[str] = typer.Argument(None), update_type: Optional[st pkg_name = list_input("Enter the package name", choices=packages) casted_update_type = _update_type_to_enum(update_type) - user_prompt_required = pkg_name is None or casted_update_type is None - if pkg_name == "ragbits-core": + if pkg_name == "ragbits": + _update_pkg_version(pkg_name, update_type=casted_update_type) + + elif pkg_name == "ragbits-core": if user_prompt_required: print("When upgrading the ragbits-core package it is also necessary to upgrade the other packages.") is_continue = confirm(message="Do you want to continue?") @@ -141,21 +221,24 @@ def run(pkg_name: Optional[str] = typer.Argument(None), update_type: Optional[st is_continue = True if is_continue: - ragbits_version, new_ragbits_version = _update_pkg_version(pkg_name, update_type=casted_update_type) - casted_update_type = _check_update_type(ragbits_version, new_ragbits_version) + version, new_version = _update_pkg_version(pkg_name, update_type=casted_update_type) + casted_update_type = _check_update_type(version, new_version) - for pkg in [pkg for pkg in packages if pkg != "ragbits-core"]: + for pkg in sorted([pkg for pkg in packages if pkg != "ragbits-core"], reverse=True): pkg_pyproject = tomlkit.parse((PACKAGES_DIR / pkg / "pyproject.toml").read_text()) pkg_pyproject["project"]["dependencies"] = [ dep for dep in pkg_pyproject["project"]["dependencies"] if "ragbits-core" not in dep ] - pkg_pyproject["project"]["dependencies"].append(f"ragbits-core=={new_ragbits_version}") + pkg_pyproject["project"]["dependencies"].append(f"ragbits-core=={new_version}") + if pkg != "ragbits": + _add_updated_dependency_to_changelog(pkg, pkg_name, new_version) _update_pkg_version(pkg, pkg_pyproject, update_type=casted_update_type) else: pprint("[red]The ragbits-core package was not successfully updated.[/red]") + else: - _update_pkg_version(pkg_name, update_type=casted_update_type) + _update_pkg_version(pkg_name, update_type=casted_update_type, sync_ragbits_version=True) if __name__ == "__main__": diff --git a/uv.lock b/uv.lock index 1c2ebf64..c9d6b69f 100644 --- a/uv.lock +++ b/uv.lock @@ -12,6 +12,7 @@ members = [ "ragbits-cli", "ragbits-core", "ragbits-document-search", + "ragbits-evaluate", "ragbits-workspace", ] @@ -131,6 +132,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, ] +[[package]] +name = "antlr4-python3-runtime" +version = "4.9.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3e/38/7859ff46355f76f8d19459005ca000b6e7012f2f1ca597746cbcd1fbfe5e/antlr4-python3-runtime-4.9.3.tar.gz", hash = "sha256:f224469b4168294902bb1efa80a8bf7855f24c99aef99cbefc1bcd3cce77881b", size = 117034 } + [[package]] name = "anyio" version = "4.6.0" @@ -146,6 +153,28 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9e/ef/7a4f225581a0d7886ea28359179cb861d7fbcdefad29663fc1167b86f69f/anyio-4.6.0-py3-none-any.whl", hash = "sha256:c7d2e9d63e31599eeb636c8c5c03a7e108d73b345f064f1c19fdc87b79036a9a", size = 89631 }, ] +[[package]] +name = "appdirs" +version = "1.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/d8/05696357e0311f5b5c316d7b95f46c669dd9c15aaeecbb48c7d0aeb88c40/appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", size = 13470 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/00/2344469e2084fb287c2e0b57b72910309874c3245463acd6cf5e3db69324/appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128", size = 9566 }, +] + +[[package]] +name = "arrow" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "types-python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2e/00/0f6e8fcdb23ea632c866620cc872729ff43ed91d284c866b515c6342b173/arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85", size = 131960 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/ed/e97229a566617f2ae958a6b13e7cc0f585470eac730a73e9e82c32a3cdd2/arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80", size = 66419 }, +] + [[package]] name = "asgiref" version = "3.8.1" @@ -238,6 +267,72 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed", size = 147925 }, ] +[[package]] +name = "boto3" +version = "1.35.42" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, + { name = "jmespath" }, + { name = "s3transfer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/e4/a60d99f727766d9801f4e14dca7e2df0245831844411562d81e0df2cc179/boto3-1.35.42.tar.gz", hash = "sha256:a5b00f8b82dce62870759f04861747944da834d64a64355970120c475efdafc0", size = 111011 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ff/7c/88d9031a7a409393da450bcfca2f3597e0afccac4cae2d97fc4e7190f012/boto3-1.35.42-py3-none-any.whl", hash = "sha256:e1f36f8be453505cebcc3da178ea081b2a06c0e5e1cdee774f1067599b8d9c3e", size = 139159 }, +] + +[[package]] +name = "botocore" +version = "1.35.42" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jmespath" }, + { name = "python-dateutil" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d3/0c/2bcd566397ab06661b222b9b5156ba0c40d5a97d3727c88ccaefea275cb4/botocore-1.35.42.tar.gz", hash = "sha256:af348636f73dc24b7e2dc760a34d08c8f2f94366e9b4c78d877307b128abecef", size = 12835012 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/f5/0e67c7e6a7f5f8c068cf444dc25d03097a22428380587542978d7ad9d86a/botocore-1.35.42-py3-none-any.whl", hash = "sha256:05af0bb8b9cea7ce7bc589c332348d338a21b784e9d088a588fd10ec145007ff", size = 12621471 }, +] + +[[package]] +name = "bravado" +version = "11.0.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "bravado-core" }, + { name = "monotonic" }, + { name = "msgpack" }, + { name = "python-dateutil" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "simplejson" }, + { name = "six" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ee/c0/63c5c888a388411839c3a421c2aa9631e6b27abc1e0ea07b7c8c6cc37323/bravado-11.0.3.tar.gz", hash = "sha256:1bb6ef75d84140c851fffe6420baaee5037d840070cfe11d60913be6ab8e0530", size = 34612 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/21/ed/03b0c36b5bcafbe2938ed222f9a164a6c0367ce99a9d2d502e462853571d/bravado-11.0.3-py2.py3-none-any.whl", hash = "sha256:8ac8bbb645e49607917a5c07808116c708521f51e80d9c29bc4a168ff4dd22c6", size = 38842 }, +] + +[[package]] +name = "bravado-core" +version = "6.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonref" }, + { name = "jsonschema", extra = ["format-nongpl"] }, + { name = "msgpack" }, + { name = "python-dateutil" }, + { name = "pytz" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "simplejson" }, + { name = "six" }, + { name = "swagger-spec-validator" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ca/6d/1ffa5c64533bc2fa436afdb9ef287cb0c0d443ef1e84db0601b0af7ce6f5/bravado-core-6.1.1.tar.gz", hash = "sha256:8cf1f7bbac2f7c696d37e970253938b5be4ddec92c8d5e64400b17469c3714b4", size = 63851 } + [[package]] name = "build" version = "1.2.2" @@ -494,6 +589,33 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", size = 46018 }, ] +[[package]] +name = "continuous-eval" +version = "0.3.13" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "appdirs" }, + { name = "imbalanced-learn" }, + { name = "mapie" }, + { name = "munkres" }, + { name = "nltk" }, + { name = "openai" }, + { name = "pandas" }, + { name = "protobuf" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "rouge" }, + { name = "sentencepiece" }, + { name = "tenacity" }, + { name = "thefuzz" }, + { name = "tqdm" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/8e/a6096693a6a19c797c309e31ab2824d3bb205a7b9eb94eff240410d260b0/continuous_eval-0.3.13.tar.gz", hash = "sha256:bab38b1a60a5223a14571d8a01e2368c6ea6d0a72155b29868d46e883bc0d085", size = 47112 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/4e/91ab1deb757d7f69fe74e2772cf8149e8bc0297a1c92ef57ff284eb8ea76/continuous_eval-0.3.13-py3-none-any.whl", hash = "sha256:b1607640d56677d988924cdd85199298255ef4a88bb7d9cea0ff0b0937d92a2d", size = 58685 }, +] + [[package]] name = "contourpy" version = "1.3.0" @@ -688,8 +810,7 @@ dependencies = [ { name = "multiprocess" }, { name = "numpy" }, { name = "packaging" }, - { name = "pandas", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, - { name = "pandas", version = "2.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "pandas" }, { name = "pyarrow" }, { name = "pyyaml" }, { name = "requests" }, @@ -865,6 +986,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/57/5e/de2e6e51cb6894f2f2bc2641f6c845561361b622e96df3cca04df77222c9/fonttools-4.54.1-py3-none-any.whl", hash = "sha256:37cddd62d83dc4f72f7c3f3c2bcf2697e89a30efb152079896544a93907733bd", size = 1096920 }, ] +[[package]] +name = "fqdn" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/3e/a80a8c077fd798951169626cde3e239adeba7dab75deb3555716415bd9b0/fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", size = 6015 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121 }, +] + [[package]] name = "frozenlist" version = "1.4.1" @@ -933,6 +1063,15 @@ http = [ { name = "aiohttp" }, ] +[[package]] +name = "future" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/b2/4140c69c6a66432916b26158687e821ba631a4c9273c474343badf84d3ba/future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05", size = 1228490 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/71/ae30dadffc90b9006d77af76b393cb9dfbfc9629f339fc1574a1c52e6806/future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216", size = 491326 }, +] + [[package]] name = "gcloud-aio-auth" version = "5.3.2" @@ -976,6 +1115,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034 }, ] +[[package]] +name = "gitdb" +version = "4.0.11" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "smmap" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/0d/bbb5b5ee188dec84647a4664f3e11b06ade2bde568dbd489d9d64adef8ed/gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b", size = 394469 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/5b/8f0c4a5bb9fd491c277c21eff7ccae71b47d43c4446c9d0c6cff2fe8c2c4/gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4", size = 62721 }, +] + +[[package]] +name = "gitpython" +version = "3.1.43" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "gitdb" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b6/a1/106fd9fa2dd989b6fb36e5893961f82992cf676381707253e0bf93eb1662/GitPython-3.1.43.tar.gz", hash = "sha256:35f314a9f878467f5453cc1fee295c3e18e52f1b99f10f6cf5b1682e968a9e7c", size = 214149 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/bd/cc3a402a6439c15c3d4294333e13042b915bbeab54edc457c723931fed3f/GitPython-3.1.43-py3-none-any.whl", hash = "sha256:eec7ec56b92aad751f9912a73404bc02ba212a23adb2c7098ee668417051a1ff", size = 207337 }, +] + [[package]] name = "google-auth" version = "2.35.0" @@ -1021,8 +1184,7 @@ dependencies = [ { name = "numpy" }, { name = "orjson" }, { name = "packaging" }, - { name = "pandas", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, - { name = "pandas", version = "2.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "pandas" }, { name = "pillow" }, { name = "pydantic" }, { name = "pydub" }, @@ -1224,6 +1386,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477", size = 86794 }, ] +[[package]] +name = "hydra-core" +version = "1.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "antlr4-python3-runtime" }, + { name = "omegaconf" }, + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/8e/07e42bc434a847154083b315779b0a81d567154504624e181caf2c71cd98/hydra-core-1.3.2.tar.gz", hash = "sha256:8a878ed67216997c3e9d88a8e72e7b4767e81af37afb4ea3334b269a4390a824", size = 3263494 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/50/e0edd38dcd63fb26a8547f13d28f7a008bc4a3fd4eb4ff030673f22ad41a/hydra_core-1.3.2-py3-none-any.whl", hash = "sha256:fa0238a9e31df3373b35b0bfb672c34cc92718d21f81311d8996a16de1141d8b", size = 154547 }, +] + [[package]] name = "identify" version = "2.6.1" @@ -1242,6 +1418,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, ] +[[package]] +name = "imbalanced-learn" +version = "0.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "joblib" }, + { name = "numpy" }, + { name = "scikit-learn" }, + { name = "scipy" }, + { name = "threadpoolctl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/56/17a02e22d2b12d864454d67ea675884d5b9dba1433809c2171dc0fe45bc6/imbalanced-learn-0.11.0.tar.gz", hash = "sha256:7582ae8858e6db0b92fef97dd08660a18297ee128d78c2abdc006b8bd86b8fdc", size = 29710391 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/9e/fbe60a768502af54563dcb59ca7856f5a8833b3ad5ada658922e1ab09b7f/imbalanced_learn-0.11.0-py3-none-any.whl", hash = "sha256:20dc7dee3c838b4d213f021bb2b4007862704160d06bd292a6bdf931590b2516", size = 235639 }, +] + [[package]] name = "importlib-metadata" version = "8.4.0" @@ -1272,6 +1464,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, ] +[[package]] +name = "isoduration" +version = "20.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "arrow" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7c/1a/3c8edc664e06e6bd06cce40c6b22da5f1429aa4224d0c590f3be21c91ead/isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", size = 11649 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321 }, +] + [[package]] name = "jinja2" version = "3.1.4" @@ -1328,6 +1532,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/15/81/296b1e25c43db67848728cdab34ac3eb5c5cbb4955ceb3f51ae60d4a5e3d/jiter-0.5.0-cp312-none-win_amd64.whl", hash = "sha256:a586832f70c3f1481732919215f36d41c59ca080fa27a65cf23d9490e75b2ef5", size = 189720 }, ] +[[package]] +name = "jmespath" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/00/2a/e867e8531cf3e36b41201936b7fa7ba7b5702dbef42922193f05c8976cd6/jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe", size = 25843 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/b4/b9b800c45527aadd64d5b442f9b932b00648617eb5d63d2c7a6587b7cafc/jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", size = 20256 }, +] + [[package]] name = "joblib" version = "1.4.2" @@ -1346,6 +1559,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/16/8a/d63959f4eff03893a00e6e63592e3a9f15b9266ed8e0275ab77f8c7dbc94/jsonpath_python-1.0.6-py3-none-any.whl", hash = "sha256:1e3b78df579f5efc23565293612decee04214609208a2335884b3ee3f786b575", size = 7552 }, ] +[[package]] +name = "jsonpointer" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595 }, +] + +[[package]] +name = "jsonref" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/0d/c1f3277e90ccdb50d33ed5ba1ec5b3f0a242ed8c1b1a85d3afeb68464dca/jsonref-1.1.0.tar.gz", hash = "sha256:32fe8e1d85af0fdefbebce950af85590b22b60f9e95443176adbde4e1ecea552", size = 8814 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/ec/e1db9922bceb168197a558a2b8c03a7963f1afe93517ddd3cf99f202f996/jsonref-1.1.0-py3-none-any.whl", hash = "sha256:590dc7773df6c21cbf948b5dac07a72a251db28b0238ceecce0a2abfa8ec30a9", size = 9425 }, +] + [[package]] name = "jsonschema" version = "4.23.0" @@ -1361,6 +1592,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/69/4a/4f9dbeb84e8850557c02365a0eee0649abe5eb1d84af92a25731c6c0f922/jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566", size = 88462 }, ] +[package.optional-dependencies] +format-nongpl = [ + { name = "fqdn" }, + { name = "idna" }, + { name = "isoduration" }, + { name = "jsonpointer" }, + { name = "rfc3339-validator" }, + { name = "rfc3986-validator" }, + { name = "uri-template" }, + { name = "webcolors" }, +] + [[package]] name = "jsonschema-specifications" version = "2023.12.1" @@ -1586,6 +1829,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ba/b2/6a22fb5c0885da3b00e116aee81f0b829ec9ac8f736cd414b4a09413fc7d/lxml-5.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:6e91cf736959057f7aac7adfc83481e03615a8e8dd5758aa1d95ea69e8931dba", size = 3487557 }, ] +[[package]] +name = "mapie" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "packaging" }, + { name = "scikit-learn" }, + { name = "scipy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9a/80/a28c0c44fd3e54d095b80981aa8185c95c6c4168ef685eaf29a9184431b6/MAPIE-0.7.0.tar.gz", hash = "sha256:4c57ddaaec4509cc784ce50a2db1928656d00e94c5e563c36499efad0e2971db", size = 157507 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/78/65821c38efac951d312eab082785cb99be418a77a1bb81f9097465a363d3/MAPIE-0.7.0-py3-none-any.whl", hash = "sha256:2edfc18d205bb5654317e69fa8998c1d37749c5737f2e04f5fdf1eb96c7cc0a2", size = 132491 }, +] + [[package]] name = "markdown" version = "3.7" @@ -1929,6 +2187,58 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198 }, ] +[[package]] +name = "msgpack" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cb/d0/7555686ae7ff5731205df1012ede15dd9d927f6227ea151e901c7406af4f/msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e", size = 167260 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/f9/a892a6038c861fa849b11a2bb0502c07bc698ab6ea53359e5771397d883b/msgpack-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ad442d527a7e358a469faf43fda45aaf4ac3249c8310a82f0ccff9164e5dccd", size = 150428 }, + { url = "https://files.pythonhosted.org/packages/df/7a/d174cc6a3b6bb85556e6a046d3193294a92f9a8e583cdbd46dc8a1d7e7f4/msgpack-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:74bed8f63f8f14d75eec75cf3d04ad581da6b914001b474a5d3cd3372c8cc27d", size = 84131 }, + { url = "https://files.pythonhosted.org/packages/08/52/bf4fbf72f897a23a56b822997a72c16de07d8d56d7bf273242f884055682/msgpack-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:914571a2a5b4e7606997e169f64ce53a8b1e06f2cf2c3a7273aa106236d43dd5", size = 81215 }, + { url = "https://files.pythonhosted.org/packages/02/95/dc0044b439b518236aaf012da4677c1b8183ce388411ad1b1e63c32d8979/msgpack-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c921af52214dcbb75e6bdf6a661b23c3e6417f00c603dd2070bccb5c3ef499f5", size = 371229 }, + { url = "https://files.pythonhosted.org/packages/ff/75/09081792db60470bef19d9c2be89f024d366b1e1973c197bb59e6aabc647/msgpack-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8ce0b22b890be5d252de90d0e0d119f363012027cf256185fc3d474c44b1b9e", size = 378034 }, + { url = "https://files.pythonhosted.org/packages/32/d3/c152e0c55fead87dd948d4b29879b0f14feeeec92ef1fd2ec21b107c3f49/msgpack-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:73322a6cc57fcee3c0c57c4463d828e9428275fb85a27aa2aa1a92fdc42afd7b", size = 363070 }, + { url = "https://files.pythonhosted.org/packages/d9/2c/82e73506dd55f9e43ac8aa007c9dd088c6f0de2aa19e8f7330e6a65879fc/msgpack-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e1f3c3d21f7cf67bcf2da8e494d30a75e4cf60041d98b3f79875afb5b96f3a3f", size = 359863 }, + { url = "https://files.pythonhosted.org/packages/cb/a0/3d093b248837094220e1edc9ec4337de3443b1cfeeb6e0896af8ccc4cc7a/msgpack-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64fc9068d701233effd61b19efb1485587560b66fe57b3e50d29c5d78e7fef68", size = 368166 }, + { url = "https://files.pythonhosted.org/packages/e4/13/7646f14f06838b406cf5a6ddbb7e8dc78b4996d891ab3b93c33d1ccc8678/msgpack-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:42f754515e0f683f9c79210a5d1cad631ec3d06cea5172214d2176a42e67e19b", size = 370105 }, + { url = "https://files.pythonhosted.org/packages/67/fa/dbbd2443e4578e165192dabbc6a22c0812cda2649261b1264ff515f19f15/msgpack-1.1.0-cp310-cp310-win32.whl", hash = "sha256:3df7e6b05571b3814361e8464f9304c42d2196808e0119f55d0d3e62cd5ea044", size = 68513 }, + { url = "https://files.pythonhosted.org/packages/24/ce/c2c8fbf0ded750cb63cbcbb61bc1f2dfd69e16dca30a8af8ba80ec182dcd/msgpack-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:685ec345eefc757a7c8af44a3032734a739f8c45d1b0ac45efc5d8977aa4720f", size = 74687 }, + { url = "https://files.pythonhosted.org/packages/b7/5e/a4c7154ba65d93be91f2f1e55f90e76c5f91ccadc7efc4341e6f04c8647f/msgpack-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d364a55082fb2a7416f6c63ae383fbd903adb5a6cf78c5b96cc6316dc1cedc7", size = 150803 }, + { url = "https://files.pythonhosted.org/packages/60/c2/687684164698f1d51c41778c838d854965dd284a4b9d3a44beba9265c931/msgpack-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79ec007767b9b56860e0372085f8504db5d06bd6a327a335449508bbee9648fa", size = 84343 }, + { url = "https://files.pythonhosted.org/packages/42/ae/d3adea9bb4a1342763556078b5765e666f8fdf242e00f3f6657380920972/msgpack-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ad622bf7756d5a497d5b6836e7fc3752e2dd6f4c648e24b1803f6048596f701", size = 81408 }, + { url = "https://files.pythonhosted.org/packages/dc/17/6313325a6ff40ce9c3207293aee3ba50104aed6c2c1559d20d09e5c1ff54/msgpack-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e59bca908d9ca0de3dc8684f21ebf9a690fe47b6be93236eb40b99af28b6ea6", size = 396096 }, + { url = "https://files.pythonhosted.org/packages/a8/a1/ad7b84b91ab5a324e707f4c9761633e357820b011a01e34ce658c1dda7cc/msgpack-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1da8f11a3dd397f0a32c76165cf0c4eb95b31013a94f6ecc0b280c05c91b59", size = 403671 }, + { url = "https://files.pythonhosted.org/packages/bb/0b/fd5b7c0b308bbf1831df0ca04ec76fe2f5bf6319833646b0a4bd5e9dc76d/msgpack-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:452aff037287acb1d70a804ffd022b21fa2bb7c46bee884dbc864cc9024128a0", size = 387414 }, + { url = "https://files.pythonhosted.org/packages/f0/03/ff8233b7c6e9929a1f5da3c7860eccd847e2523ca2de0d8ef4878d354cfa/msgpack-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8da4bf6d54ceed70e8861f833f83ce0814a2b72102e890cbdfe4b34764cdd66e", size = 383759 }, + { url = "https://files.pythonhosted.org/packages/1f/1b/eb82e1fed5a16dddd9bc75f0854b6e2fe86c0259c4353666d7fab37d39f4/msgpack-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:41c991beebf175faf352fb940bf2af9ad1fb77fd25f38d9142053914947cdbf6", size = 394405 }, + { url = "https://files.pythonhosted.org/packages/90/2e/962c6004e373d54ecf33d695fb1402f99b51832631e37c49273cc564ffc5/msgpack-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a52a1f3a5af7ba1c9ace055b659189f6c669cf3657095b50f9602af3a3ba0fe5", size = 396041 }, + { url = "https://files.pythonhosted.org/packages/f8/20/6e03342f629474414860c48aeffcc2f7f50ddaf351d95f20c3f1c67399a8/msgpack-1.1.0-cp311-cp311-win32.whl", hash = "sha256:58638690ebd0a06427c5fe1a227bb6b8b9fdc2bd07701bec13c2335c82131a88", size = 68538 }, + { url = "https://files.pythonhosted.org/packages/aa/c4/5a582fc9a87991a3e6f6800e9bb2f3c82972912235eb9539954f3e9997c7/msgpack-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd2906780f25c8ed5d7b323379f6138524ba793428db5d0e9d226d3fa6aa1788", size = 74871 }, + { url = "https://files.pythonhosted.org/packages/e1/d6/716b7ca1dbde63290d2973d22bbef1b5032ca634c3ff4384a958ec3f093a/msgpack-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d", size = 152421 }, + { url = "https://files.pythonhosted.org/packages/70/da/5312b067f6773429cec2f8f08b021c06af416bba340c912c2ec778539ed6/msgpack-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2", size = 85277 }, + { url = "https://files.pythonhosted.org/packages/28/51/da7f3ae4462e8bb98af0d5bdf2707f1b8c65a0d4f496e46b6afb06cbc286/msgpack-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420", size = 82222 }, + { url = "https://files.pythonhosted.org/packages/33/af/dc95c4b2a49cff17ce47611ca9ba218198806cad7796c0b01d1e332c86bb/msgpack-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2", size = 392971 }, + { url = "https://files.pythonhosted.org/packages/f1/54/65af8de681fa8255402c80eda2a501ba467921d5a7a028c9c22a2c2eedb5/msgpack-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39", size = 401403 }, + { url = "https://files.pythonhosted.org/packages/97/8c/e333690777bd33919ab7024269dc3c41c76ef5137b211d776fbb404bfead/msgpack-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f", size = 385356 }, + { url = "https://files.pythonhosted.org/packages/57/52/406795ba478dc1c890559dd4e89280fa86506608a28ccf3a72fbf45df9f5/msgpack-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247", size = 383028 }, + { url = "https://files.pythonhosted.org/packages/e7/69/053b6549bf90a3acadcd8232eae03e2fefc87f066a5b9fbb37e2e608859f/msgpack-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c", size = 391100 }, + { url = "https://files.pythonhosted.org/packages/23/f0/d4101d4da054f04274995ddc4086c2715d9b93111eb9ed49686c0f7ccc8a/msgpack-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b", size = 394254 }, + { url = "https://files.pythonhosted.org/packages/1c/12/cf07458f35d0d775ff3a2dc5559fa2e1fcd06c46f1ef510e594ebefdca01/msgpack-1.1.0-cp312-cp312-win32.whl", hash = "sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b", size = 69085 }, + { url = "https://files.pythonhosted.org/packages/73/80/2708a4641f7d553a63bc934a3eb7214806b5b39d200133ca7f7afb0a53e8/msgpack-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f", size = 75347 }, + { url = "https://files.pythonhosted.org/packages/c8/b0/380f5f639543a4ac413e969109978feb1f3c66e931068f91ab6ab0f8be00/msgpack-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf", size = 151142 }, + { url = "https://files.pythonhosted.org/packages/c8/ee/be57e9702400a6cb2606883d55b05784fada898dfc7fd12608ab1fdb054e/msgpack-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330", size = 84523 }, + { url = "https://files.pythonhosted.org/packages/7e/3a/2919f63acca3c119565449681ad08a2f84b2171ddfcff1dba6959db2cceb/msgpack-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734", size = 81556 }, + { url = "https://files.pythonhosted.org/packages/7c/43/a11113d9e5c1498c145a8925768ea2d5fce7cbab15c99cda655aa09947ed/msgpack-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e", size = 392105 }, + { url = "https://files.pythonhosted.org/packages/2d/7b/2c1d74ca6c94f70a1add74a8393a0138172207dc5de6fc6269483519d048/msgpack-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca", size = 399979 }, + { url = "https://files.pythonhosted.org/packages/82/8c/cf64ae518c7b8efc763ca1f1348a96f0e37150061e777a8ea5430b413a74/msgpack-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915", size = 383816 }, + { url = "https://files.pythonhosted.org/packages/69/86/a847ef7a0f5ef3fa94ae20f52a4cacf596a4e4a010197fbcc27744eb9a83/msgpack-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d", size = 380973 }, + { url = "https://files.pythonhosted.org/packages/aa/90/c74cf6e1126faa93185d3b830ee97246ecc4fe12cf9d2d31318ee4246994/msgpack-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434", size = 387435 }, + { url = "https://files.pythonhosted.org/packages/7a/40/631c238f1f338eb09f4acb0f34ab5862c4e9d7eda11c1b685471a4c5ea37/msgpack-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c", size = 399082 }, + { url = "https://files.pythonhosted.org/packages/e9/1b/fa8a952be252a1555ed39f97c06778e3aeb9123aa4cccc0fd2acd0b4e315/msgpack-1.1.0-cp313-cp313-win32.whl", hash = "sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc", size = 69037 }, + { url = "https://files.pythonhosted.org/packages/b6/bc/8bd826dd03e022153bfa1766dcdec4976d6c818865ed54223d71f07862b3/msgpack-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f", size = 75140 }, +] + [[package]] name = "multidict" version = "6.1.0" @@ -2019,6 +2329,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/da/d9/f7f9379981e39b8c2511c9e0326d212accacb82f12fbfdc1aa2ce2a7b2b6/multiprocess-0.70.16-py39-none-any.whl", hash = "sha256:a0bafd3ae1b732eac64be2e72038231c1ba97724b60b09400d68f229fcc2fbf3", size = 133351 }, ] +[[package]] +name = "munkres" +version = "1.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fd/41/6a3d0ef908f47d07c31e5d1c2504388c27c39b10b8cf610175b5a789a5c1/munkres-1.1.4.tar.gz", hash = "sha256:fc44bf3c3979dada4b6b633ddeeb8ffbe8388ee9409e4d4e8310c2da1792db03", size = 14047 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/ab/0301c945a704218bc9435f0e3c88884f6b19ef234d8899fb47ce1ccfd0c9/munkres-1.1.4-py2.py3-none-any.whl", hash = "sha256:6b01867d4a8480d865aea2326e4b8f7c46431e9e55b4a2e32d989307d7bced2a", size = 7015 }, +] + [[package]] name = "mypy-extensions" version = "1.0.0" @@ -2028,6 +2347,36 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 }, ] +[[package]] +name = "neptune" +version = "1.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "boto3" }, + { name = "bravado" }, + { name = "click" }, + { name = "future" }, + { name = "gitpython" }, + { name = "oauthlib" }, + { name = "packaging" }, + { name = "pandas" }, + { name = "pillow" }, + { name = "psutil" }, + { name = "pyjwt" }, + { name = "requests" }, + { name = "requests-oauthlib" }, + { name = "setuptools", marker = "python_full_version >= '3.12'" }, + { name = "six" }, + { name = "swagger-spec-validator" }, + { name = "typing-extensions" }, + { name = "urllib3" }, + { name = "websocket-client" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d5/fc/70a9e3e3944e2c0b7d3fc016223a479159648a4ce0e9b44316242052c2d8/neptune-1.12.0.tar.gz", hash = "sha256:ff79b3ca278c85473cd44d4857f9a22643a9a78b0015ff254599c79fb0eb659d", size = 278038 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/f3/f1c4cac2a3cddb485539908e40d8eedb079f7565ad0b1d1d33e5519f732e/neptune-1.12.0-py3-none-any.whl", hash = "sha256:5010d2a8d498117e39f770db621891643b7af7632ec1c8f581cbde4028b77214", size = 501943 }, +] + [[package]] name = "nest-asyncio" version = "1.6.0" @@ -2072,22 +2421,34 @@ wheels = [ [[package]] name = "numpy" -version = "1.24.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a4/9b/027bec52c633f6556dba6b722d9a0befb40498b9ceddd29cbe67a45a127c/numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463", size = 10911229 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/80/6cdfb3e275d95155a34659163b83c09e3a3ff9f1456880bec6cc63d71083/numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64", size = 19789140 }, - { url = "https://files.pythonhosted.org/packages/64/5f/3f01d753e2175cfade1013eea08db99ba1ee4bdb147ebcf3623b75d12aa7/numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1", size = 13854297 }, - { url = "https://files.pythonhosted.org/packages/5a/b3/2f9c21d799fa07053ffa151faccdceeb69beec5a010576b8991f614021f7/numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4", size = 13995611 }, - { url = "https://files.pythonhosted.org/packages/10/be/ae5bf4737cb79ba437879915791f6f26d92583c738d7d960ad94e5c36adf/numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6", size = 17282357 }, - { url = "https://files.pythonhosted.org/packages/c0/64/908c1087be6285f40e4b3e79454552a701664a079321cff519d8c7051d06/numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc", size = 12429222 }, - { url = "https://files.pythonhosted.org/packages/22/55/3d5a7c1142e0d9329ad27cece17933b0e2ab4e54ddc5c1861fbfeb3f7693/numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e", size = 14841514 }, - { url = "https://files.pythonhosted.org/packages/a9/cc/5ed2280a27e5dab12994c884f1f4d8c3bd4d885d02ae9e52a9d213a6a5e2/numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810", size = 19775508 }, - { url = "https://files.pythonhosted.org/packages/c0/bc/77635c657a3668cf652806210b8662e1aff84b818a55ba88257abf6637a8/numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254", size = 13840033 }, - { url = "https://files.pythonhosted.org/packages/a7/4c/96cdaa34f54c05e97c1c50f39f98d608f96f0677a6589e64e53104e22904/numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7", size = 13991951 }, - { url = "https://files.pythonhosted.org/packages/22/97/dfb1a31bb46686f09e68ea6ac5c63fdee0d22d7b23b8f3f7ea07712869ef/numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5", size = 17278923 }, - { url = "https://files.pythonhosted.org/packages/35/e2/76a11e54139654a324d107da1d98f99e7aa2a7ef97cfd7c631fba7dbde71/numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d", size = 12422446 }, - { url = "https://files.pythonhosted.org/packages/d8/ec/ebef2f7d7c28503f958f0f8b992e7ce606fb74f9e891199329d5f5f87404/numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694", size = 14834466 }, +version = "1.26.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/65/6e/09db70a523a96d25e115e71cc56a6f9031e7b8cd166c1ac8438307c14058/numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010", size = 15786129 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/94/ace0fdea5241a27d13543ee117cbc65868e82213fb31a8eb7fe9ff23f313/numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0", size = 20631468 }, + { url = "https://files.pythonhosted.org/packages/20/f7/b24208eba89f9d1b58c1668bc6c8c4fd472b20c45573cb767f59d49fb0f6/numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a", size = 13966411 }, + { url = "https://files.pythonhosted.org/packages/fc/a5/4beee6488160798683eed5bdb7eead455892c3b4e1f78d79d8d3f3b084ac/numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4", size = 14219016 }, + { url = "https://files.pythonhosted.org/packages/4b/d7/ecf66c1cd12dc28b4040b15ab4d17b773b87fa9d29ca16125de01adb36cd/numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f", size = 18240889 }, + { url = "https://files.pythonhosted.org/packages/24/03/6f229fe3187546435c4f6f89f6d26c129d4f5bed40552899fcf1f0bf9e50/numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a", size = 13876746 }, + { url = "https://files.pythonhosted.org/packages/39/fe/39ada9b094f01f5a35486577c848fe274e374bbf8d8f472e1423a0bbd26d/numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2", size = 18078620 }, + { url = "https://files.pythonhosted.org/packages/d5/ef/6ad11d51197aad206a9ad2286dc1aac6a378059e06e8cf22cd08ed4f20dc/numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07", size = 5972659 }, + { url = "https://files.pythonhosted.org/packages/19/77/538f202862b9183f54108557bfda67e17603fc560c384559e769321c9d92/numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5", size = 15808905 }, + { url = "https://files.pythonhosted.org/packages/11/57/baae43d14fe163fa0e4c47f307b6b2511ab8d7d30177c491960504252053/numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71", size = 20630554 }, + { url = "https://files.pythonhosted.org/packages/1a/2e/151484f49fd03944c4a3ad9c418ed193cfd02724e138ac8a9505d056c582/numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef", size = 13997127 }, + { url = "https://files.pythonhosted.org/packages/79/ae/7e5b85136806f9dadf4878bf73cf223fe5c2636818ba3ab1c585d0403164/numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e", size = 14222994 }, + { url = "https://files.pythonhosted.org/packages/3a/d0/edc009c27b406c4f9cbc79274d6e46d634d139075492ad055e3d68445925/numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5", size = 18252005 }, + { url = "https://files.pythonhosted.org/packages/09/bf/2b1aaf8f525f2923ff6cfcf134ae5e750e279ac65ebf386c75a0cf6da06a/numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a", size = 13885297 }, + { url = "https://files.pythonhosted.org/packages/df/a0/4e0f14d847cfc2a633a1c8621d00724f3206cfeddeb66d35698c4e2cf3d2/numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a", size = 18093567 }, + { url = "https://files.pythonhosted.org/packages/d2/b7/a734c733286e10a7f1a8ad1ae8c90f2d33bf604a96548e0a4a3a6739b468/numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20", size = 5968812 }, + { url = "https://files.pythonhosted.org/packages/3f/6b/5610004206cf7f8e7ad91c5a85a8c71b2f2f8051a0c0c4d5916b76d6cbb2/numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2", size = 15811913 }, + { url = "https://files.pythonhosted.org/packages/95/12/8f2020a8e8b8383ac0177dc9570aad031a3beb12e38847f7129bacd96228/numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218", size = 20335901 }, + { url = "https://files.pythonhosted.org/packages/75/5b/ca6c8bd14007e5ca171c7c03102d17b4f4e0ceb53957e8c44343a9546dcc/numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b", size = 13685868 }, + { url = "https://files.pythonhosted.org/packages/79/f8/97f10e6755e2a7d027ca783f63044d5b1bc1ae7acb12afe6a9b4286eac17/numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b", size = 13925109 }, + { url = "https://files.pythonhosted.org/packages/0f/50/de23fde84e45f5c4fda2488c759b69990fd4512387a8632860f3ac9cd225/numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed", size = 17950613 }, + { url = "https://files.pythonhosted.org/packages/4c/0c/9c603826b6465e82591e05ca230dfc13376da512b25ccd0894709b054ed0/numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a", size = 13572172 }, + { url = "https://files.pythonhosted.org/packages/76/8c/2ba3902e1a0fc1c74962ea9bb33a534bb05984ad7ff9515bf8d07527cadd/numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0", size = 17786643 }, + { url = "https://files.pythonhosted.org/packages/28/4a/46d9e65106879492374999e76eb85f87b15328e06bd1550668f79f7b18c6/numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110", size = 5677803 }, + { url = "https://files.pythonhosted.org/packages/16/2e/86f24451c2d530c88daf997cb8d6ac622c1d40d19f5a031ed68a4b73a374/numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818", size = 15517754 }, ] [[package]] @@ -2216,6 +2577,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/17/d3/b64c356a907242d719fc668b71befd73324e47ab46c8ebbbede252c154b2/olefile-0.47-py2.py3-none-any.whl", hash = "sha256:543c7da2a7adadf21214938bb79c83ea12b473a4b6ee4ad4bf854e7715e13d1f", size = 114565 }, ] +[[package]] +name = "omegaconf" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "antlr4-python3-runtime" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/09/48/6388f1bb9da707110532cb70ec4d2822858ddfb44f1cdf1233c20a80ea4b/omegaconf-2.3.0.tar.gz", hash = "sha256:d5d4b6d29955cc50ad50c46dc269bcd92c6e00f5f90d23ab5fee7bfca4ba4cc7", size = 3298120 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/94/1843518e420fa3ed6919835845df698c7e27e183cb997394e4a670973a65/omegaconf-2.3.0-py3-none-any.whl", hash = "sha256:7b4df175cdb08ba400f45cae3bdcae7ba8365db4d165fc65fd04b050ab63b46b", size = 79500 }, +] + [[package]] name = "onnxruntime" version = "1.19.2" @@ -2473,49 +2847,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746 }, ] -[[package]] -name = "pandas" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version == '3.12.*'", - "python_full_version >= '3.13'", -] -dependencies = [ - { name = "numpy", marker = "python_full_version >= '3.12'" }, - { name = "python-dateutil", marker = "python_full_version >= '3.12'" }, - { name = "pytz", marker = "python_full_version >= '3.12'" }, - { name = "tzdata", marker = "python_full_version >= '3.12'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/6f/31/a4a8e7367856d9584d0332793edfe631182a9cca885f12dbe2dd77c10c4a/pandas-2.1.0.tar.gz", hash = "sha256:62c24c7fc59e42b775ce0679cfa7b14a5f9bfb7643cfbe708c960699e05fb918", size = 4263970 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cf/ba/be69b6fa37c74699d333dbcbf0fc799eb31c35ce465651cdc4baf6a2e30d/pandas-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:40dd20439ff94f1b2ed55b393ecee9cb6f3b08104c2c40b0cb7186a2f0046242", size = 12118394 }, - { url = "https://files.pythonhosted.org/packages/8d/08/1cf87814dcd87604807971abc743b12e635de36d820be7b50e2b6aa9e1b5/pandas-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d4f38e4fedeba580285eaac7ede4f686c6701a9e618d8a857b138a126d067f2f", size = 11306908 }, - { url = "https://files.pythonhosted.org/packages/f3/21/8ea83d6990457c5253d9e6c40a3d2c8a3d383dfabb937b0a36a71ae43bde/pandas-2.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e6a0fe052cf27ceb29be9429428b4918f3740e37ff185658f40d8702f0b3e09", size = 15167237 }, - { url = "https://files.pythonhosted.org/packages/fb/4f/4a4372b2e24439f559b73318683486831d75e59544ae02bf8dec8dd6f48b/pandas-2.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d81e1813191070440d4c7a413cb673052b3b4a984ffd86b8dd468c45742d3cc", size = 12662125 }, - { url = "https://files.pythonhosted.org/packages/4c/a8/8ac4fa3970e64d7f62ebdcd47e507c2443d49090a3f402fa01f0e6e30b13/pandas-2.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:eb20252720b1cc1b7d0b2879ffc7e0542dd568f24d7c4b2347cb035206936421", size = 13465263 }, - { url = "https://files.pythonhosted.org/packages/c5/89/ce1c7dc497f9a20644f6a7d2dd5bce6378a48321955178197fa3b55d6fe3/pandas-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:38f74ef7ebc0ffb43b3d633e23d74882bce7e27bfa09607f3c5d3e03ffd9a4a5", size = 11097660 }, - { url = "https://files.pythonhosted.org/packages/c3/05/c5c73d54ceb7d5e4b8c046d39a1bb7f38ee76ea556a002cf3317514f0196/pandas-2.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cda72cc8c4761c8f1d97b169661f23a86b16fdb240bdc341173aee17e4d6cedd", size = 12015015 }, - { url = "https://files.pythonhosted.org/packages/e5/cd/c941b51e95992968e3e8abc7180f33b952478abd6943062051517a808db7/pandas-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d97daeac0db8c993420b10da4f5f5b39b01fc9ca689a17844e07c0a35ac96b4b", size = 11173830 }, - { url = "https://files.pythonhosted.org/packages/e2/25/bfb5c7573e2b884b18e5ea993ee7aeb5a6915ea687174349fdc5f979ceec/pandas-2.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8c58b1113892e0c8078f006a167cc210a92bdae23322bb4614f2f0b7a4b510f", size = 15176284 }, - { url = "https://files.pythonhosted.org/packages/d9/26/895a49ebddb4211f2d777150f38ef9e538deff6df7e179a3624c663efc98/pandas-2.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:629124923bcf798965b054a540f9ccdfd60f71361255c81fa1ecd94a904b9dd3", size = 12630840 }, - { url = "https://files.pythonhosted.org/packages/bc/ad/d1f0a867064f62ffde917876cc09cfd53352af2b1f147c140fd1943a0c7a/pandas-2.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:70cf866af3ab346a10debba8ea78077cf3a8cd14bd5e4bed3d41555a3280041c", size = 13463414 }, - { url = "https://files.pythonhosted.org/packages/b7/f8/32d6b5aa4c4bc045fa2c4c58f88c325facc54721956c6313f0afea8ea853/pandas-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:d53c8c1001f6a192ff1de1efe03b31a423d0eee2e9e855e69d004308e046e694", size = 11043589 }, -] - [[package]] name = "pandas" version = "2.2.3" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.11'", - "python_full_version == '3.11.*'", -] dependencies = [ - { name = "numpy", marker = "python_full_version < '3.12'" }, - { name = "python-dateutil", marker = "python_full_version < '3.12'" }, - { name = "pytz", marker = "python_full_version < '3.12'" }, - { name = "tzdata", marker = "python_full_version < '3.12'" }, + { name = "numpy" }, + { name = "python-dateutil" }, + { name = "pytz" }, + { name = "tzdata" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/9f8431bacc2e19dca897724cd097b1bb224a6ad5433784a44b587c7c13af/pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", size = 4399213 } wheels = [ @@ -2564,6 +2904,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, ] +[[package]] +name = "pdf2image" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pillow" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/d8/b280f01045555dc257b8153c00dee3bc75830f91a744cd5f84ef3a0a64b1/pdf2image-1.17.0.tar.gz", hash = "sha256:eaa959bc116b420dd7ec415fcae49b98100dda3dd18cd2fdfa86d09f112f6d57", size = 12811 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/33/61766ae033518957f877ab246f87ca30a85b778ebaad65b7f74fa7e52988/pdf2image-1.17.0-py3-none-any.whl", hash = "sha256:ecdd58d7afb810dffe21ef2b1bbc057ef434dabbac6c33778a38a3f7744a27e2", size = 11618 }, +] + [[package]] name = "pillow" version = "10.4.0" @@ -3226,7 +3578,7 @@ requires-dist = [ { name = "gradio", marker = "extra == 'lab'", specifier = "~=4.44.0" }, { name = "jinja2", specifier = ">=3.1.4" }, { name = "litellm", marker = "extra == 'litellm'", specifier = "~=1.46.0" }, - { name = "numpy", marker = "extra == 'local'", specifier = "~=1.24.0" }, + { name = "numpy", marker = "extra == 'local'", specifier = "~=1.26.0" }, { name = "pydantic", specifier = ">=2.9.1" }, { name = "pyyaml", marker = "extra == 'promptfoo'", specifier = "~=6.0.2" }, { name = "tomli", specifier = "~=2.0.2" }, @@ -3249,7 +3601,7 @@ name = "ragbits-document-search" version = "0.1.0" source = { editable = "packages/ragbits-document-search" } dependencies = [ - { name = "numpy" }, + { name = "pdf2image" }, { name = "ragbits-core" }, { name = "unstructured" }, { name = "unstructured-client" }, @@ -3277,7 +3629,7 @@ dev = [ requires-dist = [ { name = "datasets", marker = "extra == 'huggingface'", specifier = "~=3.0.1" }, { name = "gcloud-aio-storage", marker = "extra == 'gcs'", specifier = "~=9.3.0" }, - { name = "numpy", specifier = "~=1.24.0" }, + { name = "pdf2image", specifier = ">=1.17.0" }, { name = "ragbits-core", editable = "packages/ragbits-core" }, { name = "unstructured", specifier = ">=0.15.13" }, { name = "unstructured-client", specifier = ">=0.26.0" }, @@ -3293,6 +3645,45 @@ dev = [ { name = "ragbits", extras = ["litellm", "local"] }, ] +[[package]] +name = "ragbits-evaluate" +version = "0.1.0" +source = { editable = "packages/ragbits-evaluate" } +dependencies = [ + { name = "hydra-core" }, + { name = "neptune" }, +] + +[package.optional-dependencies] +relari = [ + { name = "continuous-eval" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pip-licenses" }, + { name = "pre-commit" }, + { name = "pytest" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [ + { name = "continuous-eval", marker = "extra == 'relari'", specifier = "~=0.3.12" }, + { name = "hydra-core", specifier = "~=1.3.2" }, + { name = "neptune", specifier = "~=1.12.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pip-licenses", specifier = ">=4.0.0,<5.0.0" }, + { name = "pre-commit", specifier = "~=3.8.0" }, + { name = "pytest", specifier = "~=8.3.3" }, + { name = "pytest-asyncio", specifier = "~=0.24.0" }, + { name = "pytest-cov", specifier = "~=5.0.0" }, +] + [[package]] name = "ragbits-workspace" version = "0.1.0" @@ -3301,6 +3692,7 @@ dependencies = [ { name = "ragbits-cli" }, { name = "ragbits-core", extra = ["chromadb", "lab", "litellm", "local"] }, { name = "ragbits-document-search", extra = ["gcs", "huggingface"] }, + { name = "ragbits-evaluate", extra = ["relari"] }, ] [package.dev-dependencies] @@ -3325,6 +3717,7 @@ requires-dist = [ { name = "ragbits-cli", editable = "packages/ragbits-cli" }, { name = "ragbits-core", extras = ["litellm", "local", "lab", "chromadb"], editable = "packages/ragbits-core" }, { name = "ragbits-document-search", extras = ["gcs", "huggingface"], editable = "packages/ragbits-document-search" }, + { name = "ragbits-evaluate", extras = ["relari"], editable = "packages/ragbits-evaluate" }, ] [package.metadata.requires-dev] @@ -3540,6 +3933,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481 }, ] +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490 }, +] + +[[package]] +name = "rfc3986-validator" +version = "0.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/88/f270de456dd7d11dcc808abfa291ecdd3f45ff44e3b549ffa01b126464d0/rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055", size = 6760 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", size = 4242 }, +] + [[package]] name = "rich" version = "13.9.1" @@ -3554,6 +3968,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ab/71/cd9549551f1aa11cf7e5f92bae5817979e8b3a19e31e8810c15f3f45c311/rich-13.9.1-py3-none-any.whl", hash = "sha256:b340e739f30aa58921dc477b8adaa9ecdb7cecc217be01d93730ee1bc8aa83be", size = 242147 }, ] +[[package]] +name = "rouge" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/db/e4/3420a1ab1e82a280fb6107f7ae99e88eb12383c978fe573c0c64d0327d6b/rouge-1.0.1.tar.gz", hash = "sha256:12b48346ca47d6bcf3c45061f315452b9ccec0620ee895ec85b7efc3d54aae34", size = 14292 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/7c/650ae86f92460e9e8ef969cc5008b24798dcf56a9a8947d04c78f550b3f5/rouge-1.0.1-py3-none-any.whl", hash = "sha256:28d118536e8c774dc47d1d15ec266479b4dd0914c4672ce117d4002789bdc644", size = 13725 }, +] + [[package]] name = "rpds-py" version = "0.20.0" @@ -3663,6 +4089,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d9/bd/a8b0c64945a92eaeeb8d0283f27a726a776a1c9d12734d990c5fc7a1278c/ruff-0.6.8-py3-none-win_arm64.whl", hash = "sha256:8d3bb2e3fbb9875172119021a13eed38849e762499e3cfde9588e4b4d70968dc", size = 8669595 }, ] +[[package]] +name = "s3transfer" +version = "0.10.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a0/a8/e0a98fd7bd874914f0608ef7c90ffde17e116aefad765021de0f012690a2/s3transfer-0.10.3.tar.gz", hash = "sha256:4f50ed74ab84d474ce614475e0b8d5047ff080810aac5d01ea25231cfc944b0c", size = 144591 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/c0/b0fba8259b61c938c9733da9346b9f93e00881a9db22aafdd72f6ae0ec05/s3transfer-0.10.3-py3-none-any.whl", hash = "sha256:263ed587a5803c6c708d3ce44dc4dfedaab4c1a32e8329bab818933d79ddcf5d", size = 82625 }, +] + [[package]] name = "safetensors" version = "0.4.5" @@ -3724,6 +4162,83 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/19/46/5d11dc300feaad285c2f1bd784ff3f689f5e0ab6be49aaf568f3a77019eb/safetensors-0.4.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:21742b391b859e67b26c0b2ac37f52c9c0944a879a25ad2f9f9f3cd61e7fda8f", size = 606660 }, ] +[[package]] +name = "scikit-learn" +version = "1.5.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "joblib" }, + { name = "numpy" }, + { name = "scipy" }, + { name = "threadpoolctl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/37/59/44985a2bdc95c74e34fef3d10cb5d93ce13b0e2a7baefffe1b53853b502d/scikit_learn-1.5.2.tar.gz", hash = "sha256:b4237ed7b3fdd0a4882792e68ef2545d5baa50aca3bb45aa7df468138ad8f94d", size = 7001680 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/89/be41419b4bec629a4691183a5eb1796f91252a13a5ffa243fd958cad7e91/scikit_learn-1.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:299406827fb9a4f862626d0fe6c122f5f87f8910b86fe5daa4c32dcd742139b6", size = 12106070 }, + { url = "https://files.pythonhosted.org/packages/bf/e0/3b6d777d375f3b685f433c93384cdb724fb078e1dc8f8ff0950467e56c30/scikit_learn-1.5.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:2d4cad1119c77930b235579ad0dc25e65c917e756fe80cab96aa3b9428bd3fb0", size = 10971758 }, + { url = "https://files.pythonhosted.org/packages/7b/31/eb7dd56c371640753953277de11356c46a3149bfeebb3d7dcd90b993715a/scikit_learn-1.5.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c412ccc2ad9bf3755915e3908e677b367ebc8d010acbb3f182814524f2e5540", size = 12500080 }, + { url = "https://files.pythonhosted.org/packages/4c/1e/a7c7357e704459c7d56a18df4a0bf08669442d1f8878cc0864beccd6306a/scikit_learn-1.5.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a686885a4b3818d9e62904d91b57fa757fc2bed3e465c8b177be652f4dd37c8", size = 13347241 }, + { url = "https://files.pythonhosted.org/packages/48/76/154ebda6794faf0b0f3ccb1b5cd9a19f0a63cb9e1f3d2c61b6114002677b/scikit_learn-1.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:c15b1ca23d7c5f33cc2cb0a0d6aaacf893792271cddff0edbd6a40e8319bc113", size = 11000477 }, + { url = "https://files.pythonhosted.org/packages/ff/91/609961972f694cb9520c4c3d201e377a26583e1eb83bc5a334c893729214/scikit_learn-1.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:03b6158efa3faaf1feea3faa884c840ebd61b6484167c711548fce208ea09445", size = 12088580 }, + { url = "https://files.pythonhosted.org/packages/cd/7a/19fe32c810c5ceddafcfda16276d98df299c8649e24e84d4f00df4a91e01/scikit_learn-1.5.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:1ff45e26928d3b4eb767a8f14a9a6efbf1cbff7c05d1fb0f95f211a89fd4f5de", size = 10975994 }, + { url = "https://files.pythonhosted.org/packages/4c/75/62e49f8a62bf3c60b0e64d0fce540578ee4f0e752765beb2e1dc7c6d6098/scikit_learn-1.5.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f763897fe92d0e903aa4847b0aec0e68cadfff77e8a0687cabd946c89d17e675", size = 12465782 }, + { url = "https://files.pythonhosted.org/packages/49/21/3723de321531c9745e40f1badafd821e029d346155b6c79704e0b7197552/scikit_learn-1.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8b0ccd4a902836493e026c03256e8b206656f91fbcc4fde28c57a5b752561f1", size = 13322034 }, + { url = "https://files.pythonhosted.org/packages/17/1c/ccdd103cfcc9435a18819856fbbe0c20b8fa60bfc3343580de4be13f0668/scikit_learn-1.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:6c16d84a0d45e4894832b3c4d0bf73050939e21b99b01b6fd59cbb0cf39163b6", size = 11015224 }, + { url = "https://files.pythonhosted.org/packages/a4/db/b485c1ac54ff3bd9e7e6b39d3cc6609c4c76a65f52ab0a7b22b6c3ab0e9d/scikit_learn-1.5.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f932a02c3f4956dfb981391ab24bda1dbd90fe3d628e4b42caef3e041c67707a", size = 12110344 }, + { url = "https://files.pythonhosted.org/packages/54/1a/7deb52fa23aebb855431ad659b3c6a2e1709ece582cb3a63d66905e735fe/scikit_learn-1.5.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:3b923d119d65b7bd555c73be5423bf06c0105678ce7e1f558cb4b40b0a5502b1", size = 11033502 }, + { url = "https://files.pythonhosted.org/packages/a1/32/4a7a205b14c11225609b75b28402c196e4396ac754dab6a81971b811781c/scikit_learn-1.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f60021ec1574e56632be2a36b946f8143bf4e5e6af4a06d85281adc22938e0dd", size = 12085794 }, + { url = "https://files.pythonhosted.org/packages/c6/29/044048c5e911373827c0e1d3051321b9183b2a4f8d4e2f11c08fcff83f13/scikit_learn-1.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:394397841449853c2290a32050382edaec3da89e35b3e03d6cc966aebc6a8ae6", size = 12945797 }, + { url = "https://files.pythonhosted.org/packages/aa/ce/c0b912f2f31aeb1b756a6ba56bcd84dd1f8a148470526a48515a3f4d48cd/scikit_learn-1.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:57cc1786cfd6bd118220a92ede80270132aa353647684efa385a74244a41e3b1", size = 10985467 }, + { url = "https://files.pythonhosted.org/packages/a4/50/8891028437858cc510e13578fe7046574a60c2aaaa92b02d64aac5b1b412/scikit_learn-1.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9a702e2de732bbb20d3bad29ebd77fc05a6b427dc49964300340e4c9328b3f5", size = 12025584 }, + { url = "https://files.pythonhosted.org/packages/d2/79/17feef8a1c14149436083bec0e61d7befb4812e272d5b20f9d79ea3e9ab1/scikit_learn-1.5.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:b0768ad641981f5d3a198430a1d31c3e044ed2e8a6f22166b4d546a5116d7908", size = 10959795 }, + { url = "https://files.pythonhosted.org/packages/b1/c8/f08313f9e2e656bd0905930ae8bf99a573ea21c34666a813b749c338202f/scikit_learn-1.5.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:178ddd0a5cb0044464fc1bfc4cca5b1833bfc7bb022d70b05db8530da4bb3dd3", size = 12077302 }, + { url = "https://files.pythonhosted.org/packages/a7/48/fbfb4dc72bed0fe31fe045fb30e924909ad03f717c36694351612973b1a9/scikit_learn-1.5.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7284ade780084d94505632241bf78c44ab3b6f1e8ccab3d2af58e0e950f9c12", size = 13002811 }, + { url = "https://files.pythonhosted.org/packages/a5/e7/0c869f9e60d225a77af90d2aefa7a4a4c0e745b149325d1450f0f0ce5399/scikit_learn-1.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:b7b0f9a0b1040830d38c39b91b3a44e1b643f4b36e36567b80b7c6bd2202a27f", size = 10951354 }, +] + +[[package]] +name = "scipy" +version = "1.14.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/62/11/4d44a1f274e002784e4dbdb81e0ea96d2de2d1045b2132d5af62cc31fd28/scipy-1.14.1.tar.gz", hash = "sha256:5a275584e726026a5699459aa72f828a610821006228e841b94275c4a7c08417", size = 58620554 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/68/3bc0cfaf64ff507d82b1e5d5b64521df4c8bf7e22bc0b897827cbee9872c/scipy-1.14.1-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:b28d2ca4add7ac16ae8bb6632a3c86e4b9e4d52d3e34267f6e1b0c1f8d87e389", size = 39069598 }, + { url = "https://files.pythonhosted.org/packages/43/a5/8d02f9c372790326ad405d94f04d4339482ec082455b9e6e288f7100513b/scipy-1.14.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d0d2821003174de06b69e58cef2316a6622b60ee613121199cb2852a873f8cf3", size = 29879676 }, + { url = "https://files.pythonhosted.org/packages/07/42/0e0bea9666fcbf2cb6ea0205db42c81b1f34d7b729ba251010edf9c80ebd/scipy-1.14.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8bddf15838ba768bb5f5083c1ea012d64c9a444e16192762bd858f1e126196d0", size = 23088696 }, + { url = "https://files.pythonhosted.org/packages/15/47/298ab6fef5ebf31b426560e978b8b8548421d4ed0bf99263e1eb44532306/scipy-1.14.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:97c5dddd5932bd2a1a31c927ba5e1463a53b87ca96b5c9bdf5dfd6096e27efc3", size = 25470699 }, + { url = "https://files.pythonhosted.org/packages/d8/df/cdb6be5274bc694c4c22862ac3438cb04f360ed9df0aecee02ce0b798380/scipy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ff0a7e01e422c15739ecd64432743cf7aae2b03f3084288f399affcefe5222d", size = 35606631 }, + { url = "https://files.pythonhosted.org/packages/47/78/b0c2c23880dd1e99e938ad49ccfb011ae353758a2dc5ed7ee59baff684c3/scipy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e32dced201274bf96899e6491d9ba3e9a5f6b336708656466ad0522d8528f69", size = 41178528 }, + { url = "https://files.pythonhosted.org/packages/5d/aa/994b45c34b897637b853ec04334afa55a85650a0d11dacfa67232260fb0a/scipy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8426251ad1e4ad903a4514712d2fa8fdd5382c978010d1c6f5f37ef286a713ad", size = 42784535 }, + { url = "https://files.pythonhosted.org/packages/e7/1c/8daa6df17a945cb1a2a1e3bae3c49643f7b3b94017ff01a4787064f03f84/scipy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:a49f6ed96f83966f576b33a44257d869756df6cf1ef4934f59dd58b25e0327e5", size = 44772117 }, + { url = "https://files.pythonhosted.org/packages/b2/ab/070ccfabe870d9f105b04aee1e2860520460ef7ca0213172abfe871463b9/scipy-1.14.1-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:2da0469a4ef0ecd3693761acbdc20f2fdeafb69e6819cc081308cc978153c675", size = 39076999 }, + { url = "https://files.pythonhosted.org/packages/a7/c5/02ac82f9bb8f70818099df7e86c3ad28dae64e1347b421d8e3adf26acab6/scipy-1.14.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:c0ee987efa6737242745f347835da2cc5bb9f1b42996a4d97d5c7ff7928cb6f2", size = 29894570 }, + { url = "https://files.pythonhosted.org/packages/ed/05/7f03e680cc5249c4f96c9e4e845acde08eb1aee5bc216eff8a089baa4ddb/scipy-1.14.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3a1b111fac6baec1c1d92f27e76511c9e7218f1695d61b59e05e0fe04dc59617", size = 23103567 }, + { url = "https://files.pythonhosted.org/packages/5e/fc/9f1413bef53171f379d786aabc104d4abeea48ee84c553a3e3d8c9f96a9c/scipy-1.14.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8475230e55549ab3f207bff11ebfc91c805dc3463ef62eda3ccf593254524ce8", size = 25499102 }, + { url = "https://files.pythonhosted.org/packages/c2/4b/b44bee3c2ddc316b0159b3d87a3d467ef8d7edfd525e6f7364a62cd87d90/scipy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:278266012eb69f4a720827bdd2dc54b2271c97d84255b2faaa8f161a158c3b37", size = 35586346 }, + { url = "https://files.pythonhosted.org/packages/93/6b/701776d4bd6bdd9b629c387b5140f006185bd8ddea16788a44434376b98f/scipy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fef8c87f8abfb884dac04e97824b61299880c43f4ce675dd2cbeadd3c9b466d2", size = 41165244 }, + { url = "https://files.pythonhosted.org/packages/06/57/e6aa6f55729a8f245d8a6984f2855696c5992113a5dc789065020f8be753/scipy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b05d43735bb2f07d689f56f7b474788a13ed8adc484a85aa65c0fd931cf9ccd2", size = 42817917 }, + { url = "https://files.pythonhosted.org/packages/ea/c2/5ecadc5fcccefaece775feadcd795060adf5c3b29a883bff0e678cfe89af/scipy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:716e389b694c4bb564b4fc0c51bc84d381735e0d39d3f26ec1af2556ec6aad94", size = 44781033 }, + { url = "https://files.pythonhosted.org/packages/c0/04/2bdacc8ac6387b15db6faa40295f8bd25eccf33f1f13e68a72dc3c60a99e/scipy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:631f07b3734d34aced009aaf6fedfd0eb3498a97e581c3b1e5f14a04164a456d", size = 39128781 }, + { url = "https://files.pythonhosted.org/packages/c8/53/35b4d41f5fd42f5781dbd0dd6c05d35ba8aa75c84ecddc7d44756cd8da2e/scipy-1.14.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:af29a935803cc707ab2ed7791c44288a682f9c8107bc00f0eccc4f92c08d6e07", size = 29939542 }, + { url = "https://files.pythonhosted.org/packages/66/67/6ef192e0e4d77b20cc33a01e743b00bc9e68fb83b88e06e636d2619a8767/scipy-1.14.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2843f2d527d9eebec9a43e6b406fb7266f3af25a751aa91d62ff416f54170bc5", size = 23148375 }, + { url = "https://files.pythonhosted.org/packages/f6/32/3a6dedd51d68eb7b8e7dc7947d5d841bcb699f1bf4463639554986f4d782/scipy-1.14.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:eb58ca0abd96911932f688528977858681a59d61a7ce908ffd355957f7025cfc", size = 25578573 }, + { url = "https://files.pythonhosted.org/packages/f0/5a/efa92a58dc3a2898705f1dc9dbaf390ca7d4fba26d6ab8cfffb0c72f656f/scipy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30ac8812c1d2aab7131a79ba62933a2a76f582d5dbbc695192453dae67ad6310", size = 35319299 }, + { url = "https://files.pythonhosted.org/packages/8e/ee/8a26858ca517e9c64f84b4c7734b89bda8e63bec85c3d2f432d225bb1886/scipy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f9ea80f2e65bdaa0b7627fb00cbeb2daf163caa015e59b7516395fe3bd1e066", size = 40849331 }, + { url = "https://files.pythonhosted.org/packages/a5/cd/06f72bc9187840f1c99e1a8750aad4216fc7dfdd7df46e6280add14b4822/scipy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:edaf02b82cd7639db00dbff629995ef185c8df4c3ffa71a5562a595765a06ce1", size = 42544049 }, + { url = "https://files.pythonhosted.org/packages/aa/7d/43ab67228ef98c6b5dd42ab386eae2d7877036970a0d7e3dd3eb47a0d530/scipy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2ff38e22128e6c03ff73b6bb0f85f897d2362f8c052e3b8ad00532198fbdae3f", size = 44521212 }, + { url = "https://files.pythonhosted.org/packages/50/ef/ac98346db016ff18a6ad7626a35808f37074d25796fd0234c2bb0ed1e054/scipy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1729560c906963fc8389f6aac023739ff3983e727b1a4d87696b7bf108316a79", size = 39091068 }, + { url = "https://files.pythonhosted.org/packages/b9/cc/70948fe9f393b911b4251e96b55bbdeaa8cca41f37c26fd1df0232933b9e/scipy-1.14.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:4079b90df244709e675cdc8b93bfd8a395d59af40b72e339c2287c91860deb8e", size = 29875417 }, + { url = "https://files.pythonhosted.org/packages/3b/2e/35f549b7d231c1c9f9639f9ef49b815d816bf54dd050da5da1c11517a218/scipy-1.14.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e0cf28db0f24a38b2a0ca33a85a54852586e43cf6fd876365c86e0657cfe7d73", size = 23084508 }, + { url = "https://files.pythonhosted.org/packages/3f/d6/b028e3f3e59fae61fb8c0f450db732c43dd1d836223a589a8be9f6377203/scipy-1.14.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0c2f95de3b04e26f5f3ad5bb05e74ba7f68b837133a4492414b3afd79dfe540e", size = 25503364 }, + { url = "https://files.pythonhosted.org/packages/a7/2f/6c142b352ac15967744d62b165537a965e95d557085db4beab2a11f7943b/scipy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b99722ea48b7ea25e8e015e8341ae74624f72e5f21fc2abd45f3a93266de4c5d", size = 35292639 }, + { url = "https://files.pythonhosted.org/packages/56/46/2449e6e51e0d7c3575f289f6acb7f828938eaab8874dbccfeb0cd2b71a27/scipy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5149e3fd2d686e42144a093b206aef01932a0059c2a33ddfa67f5f035bdfe13e", size = 40798288 }, + { url = "https://files.pythonhosted.org/packages/32/cd/9d86f7ed7f4497c9fd3e39f8918dd93d9f647ba80d7e34e4946c0c2d1a7c/scipy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4f5a7c49323533f9103d4dacf4e4f07078f360743dec7f7596949149efeec06", size = 42524647 }, + { url = "https://files.pythonhosted.org/packages/f5/1b/6ee032251bf4cdb0cc50059374e86a9f076308c1512b61c4e003e241efb7/scipy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:baff393942b550823bfce952bb62270ee17504d02a1801d7fd0719534dfb9c84", size = 44469524 }, +] + [[package]] name = "semantic-version" version = "2.10.0" @@ -3733,6 +4248,38 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6a/23/8146aad7d88f4fcb3a6218f41a60f6c2d4e3a72de72da1825dc7c8f7877c/semantic_version-2.10.0-py2.py3-none-any.whl", hash = "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177", size = 15552 }, ] +[[package]] +name = "sentencepiece" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/d2/b9c7ca067c26d8ff085d252c89b5f69609ca93fb85a00ede95f4857865d4/sentencepiece-0.2.0.tar.gz", hash = "sha256:a52c19171daaf2e697dc6cbe67684e0fa341b1248966f6aebb541de654d15843", size = 2632106 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/71/98648c3b64b23edb5403f74bcc906ad21766872a6e1ada26ea3f1eb941ab/sentencepiece-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:188779e1298a1c8b8253c7d3ad729cb0a9891e5cef5e5d07ce4592c54869e227", size = 2408979 }, + { url = "https://files.pythonhosted.org/packages/77/9f/7efbaa6d4c0c718a9affbecc536b03ca62f99f421bdffb531c16030e2d2b/sentencepiece-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bed9cf85b296fa2b76fc2547b9cbb691a523864cebaee86304c43a7b4cb1b452", size = 1238845 }, + { url = "https://files.pythonhosted.org/packages/1c/e4/c2541027a43ec6962ba9b601805d17ba3f86b38bdeae0e8ac65a2981e248/sentencepiece-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d7b67e724bead13f18db6e1d10b6bbdc454af574d70efbb36f27d90387be1ca3", size = 1181472 }, + { url = "https://files.pythonhosted.org/packages/fd/46/316c1ba6c52b97de76aff7b9da678f7afbb52136afb2987c474d95630e65/sentencepiece-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fde4b08cfe237be4484c6c7c2e2c75fb862cfeab6bd5449ce4caeafd97b767a", size = 1259151 }, + { url = "https://files.pythonhosted.org/packages/aa/5a/3c48738a0835d76dd06c62b6ac48d39c923cde78dd0f587353bdcbb99851/sentencepiece-0.2.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c378492056202d1c48a4979650981635fd97875a00eabb1f00c6a236b013b5e", size = 1355931 }, + { url = "https://files.pythonhosted.org/packages/a6/27/33019685023221ca8ed98e8ceb7ae5e166032686fa3662c68f1f1edf334e/sentencepiece-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1380ce6540a368de2ef6d7e6ba14ba8f3258df650d39ba7d833b79ee68a52040", size = 1301537 }, + { url = "https://files.pythonhosted.org/packages/ca/e4/55f97cef14293171fef5f96e96999919ab5b4d1ce95b53547ad653d7e3bf/sentencepiece-0.2.0-cp310-cp310-win32.whl", hash = "sha256:a1151d6a6dd4b43e552394aed0edfe9292820272f0194bd56c7c1660a0c06c3d", size = 936747 }, + { url = "https://files.pythonhosted.org/packages/85/f4/4ef1a6e0e9dbd8a60780a91df8b7452ada14cfaa0e17b3b8dfa42cecae18/sentencepiece-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:d490142b0521ef22bc1085f061d922a2a6666175bb6b42e588ff95c0db6819b2", size = 991525 }, + { url = "https://files.pythonhosted.org/packages/32/43/8f8885168a47a02eba1455bd3f4f169f50ad5b8cebd2402d0f5e20854d04/sentencepiece-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:17982700c4f6dbb55fa3594f3d7e5dd1c8659a274af3738e33c987d2a27c9d5c", size = 2409036 }, + { url = "https://files.pythonhosted.org/packages/0f/35/e63ba28062af0a3d688a9f128e407a1a2608544b2f480cb49bf7f4b1cbb9/sentencepiece-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7c867012c0e8bcd5bdad0f791609101cb5c66acb303ab3270218d6debc68a65e", size = 1238921 }, + { url = "https://files.pythonhosted.org/packages/de/42/ae30952c4a0bd773e90c9bf2579f5533037c886dfc8ec68133d5694f4dd2/sentencepiece-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7fd6071249c74f779c5b27183295b9202f8dedb68034e716784364443879eaa6", size = 1181477 }, + { url = "https://files.pythonhosted.org/packages/e3/ac/2f2ab1d60bb2d795d054eebe5e3f24b164bc21b5a9b75fba7968b3b91b5a/sentencepiece-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27f90c55a65013cbb8f4d7aab0599bf925cde4adc67ae43a0d323677b5a1c6cb", size = 1259182 }, + { url = "https://files.pythonhosted.org/packages/45/fb/14633c6ecf262c468759ffcdb55c3a7ee38fe4eda6a70d75ee7c7d63c58b/sentencepiece-0.2.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b293734059ef656dcd65be62ff771507bea8fed0a711b6733976e1ed3add4553", size = 1355537 }, + { url = "https://files.pythonhosted.org/packages/fb/12/2f5c8d4764b00033cf1c935b702d3bb878d10be9f0b87f0253495832d85f/sentencepiece-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e58b47f933aca74c6a60a79dcb21d5b9e47416256c795c2d58d55cec27f9551d", size = 1301464 }, + { url = "https://files.pythonhosted.org/packages/4e/b1/67afc0bde24f6dcb3acdea0dd8dcdf4b8b0db240f6bacd39378bd32d09f8/sentencepiece-0.2.0-cp311-cp311-win32.whl", hash = "sha256:c581258cf346b327c62c4f1cebd32691826306f6a41d8c4bec43b010dee08e75", size = 936749 }, + { url = "https://files.pythonhosted.org/packages/a2/f6/587c62fd21fc988555b85351f50bbde43a51524caafd63bc69240ded14fd/sentencepiece-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:0993dbc665f4113017892f1b87c3904a44d0640eda510abcacdfb07f74286d36", size = 991520 }, + { url = "https://files.pythonhosted.org/packages/27/5a/141b227ed54293360a9ffbb7bf8252b4e5efc0400cdeac5809340e5d2b21/sentencepiece-0.2.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ea5f536e32ea8ec96086ee00d7a4a131ce583a1b18d130711707c10e69601cb2", size = 2409370 }, + { url = "https://files.pythonhosted.org/packages/2e/08/a4c135ad6fc2ce26798d14ab72790d66e813efc9589fd30a5316a88ca8d5/sentencepiece-0.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d0cb51f53b6aae3c36bafe41e86167c71af8370a039f542c43b0cce5ef24a68c", size = 1239288 }, + { url = "https://files.pythonhosted.org/packages/49/0a/2fe387f825ac5aad5a0bfe221904882106cac58e1b693ba7818785a882b6/sentencepiece-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3212121805afc58d8b00ab4e7dd1f8f76c203ddb9dc94aa4079618a31cf5da0f", size = 1181597 }, + { url = "https://files.pythonhosted.org/packages/cc/38/e4698ee2293fe4835dc033c49796a39b3eebd8752098f6bd0aa53a14af1f/sentencepiece-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a3149e3066c2a75e0d68a43eb632d7ae728c7925b517f4c05c40f6f7280ce08", size = 1259220 }, + { url = "https://files.pythonhosted.org/packages/12/24/fd7ef967c9dad2f6e6e5386d0cadaf65cda8b7be6e3861a9ab3121035139/sentencepiece-0.2.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:632f3594d3e7ac8b367bca204cb3fd05a01d5b21455acd097ea4c0e30e2f63d7", size = 1355962 }, + { url = "https://files.pythonhosted.org/packages/4f/d2/18246f43ca730bb81918f87b7e886531eda32d835811ad9f4657c54eee35/sentencepiece-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f295105c6bdbb05bd5e1b0cafbd78ff95036f5d3641e7949455a3f4e5e7c3109", size = 1301706 }, + { url = "https://files.pythonhosted.org/packages/8a/47/ca237b562f420044ab56ddb4c278672f7e8c866e183730a20e413b38a989/sentencepiece-0.2.0-cp312-cp312-win32.whl", hash = "sha256:fb89f811e5efd18bab141afc3fea3de141c3f69f3fe9e898f710ae7fe3aab251", size = 936941 }, + { url = "https://files.pythonhosted.org/packages/c6/97/d159c32642306ee2b70732077632895438867b3b6df282354bd550cf2a67/sentencepiece-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7a673a72aab81fef5ebe755c6e0cc60087d1f3a4700835d40537183c1703a45f", size = 991994 }, +] + [[package]] name = "setuptools" version = "75.1.0" @@ -3751,6 +4298,67 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 }, ] +[[package]] +name = "simplejson" +version = "3.19.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3d/29/085111f19717f865eceaf0d4397bf3e76b08d60428b076b64e2a1903706d/simplejson-3.19.3.tar.gz", hash = "sha256:8e086896c36210ab6050f2f9f095a5f1e03c83fa0e7f296d6cba425411364680", size = 85237 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/24/260ad03435ce8ef2436031951134659c7161776ec3a78094b35b9375ceea/simplejson-3.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:50d8b742d74c449c4dcac570d08ce0f21f6a149d2d9cf7652dbf2ba9a1bc729a", size = 93660 }, + { url = "https://files.pythonhosted.org/packages/63/a1/dee207f357bcd6b106f2ca5129ee916c24993ba08b7dfbf9a37c22442ea9/simplejson-3.19.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd011fc3c1d88b779645495fdb8189fb318a26981eebcce14109460e062f209b", size = 75546 }, + { url = "https://files.pythonhosted.org/packages/80/7b/45ef1da43f54d209ce2ef59b7356cda13f810186c381f38ae23a4d2b1337/simplejson-3.19.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:637c4d4b81825c1f4d651e56210bd35b5604034b192b02d2d8f17f7ce8c18f42", size = 75602 }, + { url = "https://files.pythonhosted.org/packages/7f/4b/9a132382982f8127bc7ce5212a5585d83c174707c9dd698d0cb6a0d41882/simplejson-3.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f56eb03bc9e432bb81adc8ecff2486d39feb371abb442964ffb44f6db23b332", size = 138632 }, + { url = "https://files.pythonhosted.org/packages/76/37/012f5ad2f38afa28f8a6ad9da01dc0b64492ffbaf2a3f2f8a0e1fddf9c1d/simplejson-3.19.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ef59a53be400c1fad2c914b8d74c9d42384fed5174f9321dd021b7017fd40270", size = 146740 }, + { url = "https://files.pythonhosted.org/packages/69/b3/89640bd676e26ea2315b5aaf80712a6fbbb4338e4caf872d91448502a19b/simplejson-3.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72e8abbc86fcac83629a030888b45fed3a404d54161118be52cb491cd6975d3e", size = 134440 }, + { url = "https://files.pythonhosted.org/packages/61/20/0035a288deaff05397d6cc0145b33f3dd2429b99cdc880de4c5eca41ca72/simplejson-3.19.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8efb03ca77bd7725dfacc9254df00d73e6f43013cf39bd37ef1a8ed0ebb5165", size = 137949 }, + { url = "https://files.pythonhosted.org/packages/5d/de/5b03fafe3003e32d179588953d38183af6c3747e95c7dcc668c4f9eb886a/simplejson-3.19.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:add8850db04b98507a8b62d248a326ecc8561e6d24336d1ca5c605bbfaab4cad", size = 139992 }, + { url = "https://files.pythonhosted.org/packages/d1/ce/e493116ff49fd215f7baa25195b8f684c91e65c153e2a57e04dc3f3a466b/simplejson-3.19.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fc3dc9fb413fc34c396f52f4c87de18d0bd5023804afa8ab5cc224deeb6a9900", size = 140320 }, + { url = "https://files.pythonhosted.org/packages/86/f3/a18b98a7a27548829f672754dd3940fb637a27981399838128d3e560087f/simplejson-3.19.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4dfa420bb9225dd33b6efdabde7c6a671b51150b9b1d9c4e5cd74d3b420b3fe1", size = 148625 }, + { url = "https://files.pythonhosted.org/packages/0f/55/d3da33ee3e708133da079b9d537693d7fef281e6f0d27921cc7e5b3ec523/simplejson-3.19.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7b5c472099b39b274dcde27f1113db8d818c9aa3ba8f78cbb8ad04a4c1ac2118", size = 141287 }, + { url = "https://files.pythonhosted.org/packages/17/e8/56184ab4d66bb64a6ff569f069b3796dfd943f9b961268fe0d403526fc17/simplejson-3.19.3-cp310-cp310-win32.whl", hash = "sha256:817abad79241ed4a507b3caf4d3f2be5079f39d35d4c550a061988986bffd2ec", size = 74143 }, + { url = "https://files.pythonhosted.org/packages/be/8f/a0089eff060f10a925f08b0a0f50854321484f1ac54b1895bbf4c9213dfe/simplejson-3.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:dd5b9b1783e14803e362a558680d88939e830db2466f3fa22df5c9319f8eea94", size = 75643 }, + { url = "https://files.pythonhosted.org/packages/8c/bb/9ee3959e6929d228cf669b3f13f0edd43c5261b6cd69598640748b19ca35/simplejson-3.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e88abff510dcff903a18d11c2a75f9964e768d99c8d147839913886144b2065e", size = 91930 }, + { url = "https://files.pythonhosted.org/packages/ac/ae/a06523928af3a6783e2638cd4f6035c3e32de1c1063d563d9060c8d2f1ad/simplejson-3.19.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:934a50a614fb831614db5dbfba35127ee277624dda4d15895c957d2f5d48610c", size = 74787 }, + { url = "https://files.pythonhosted.org/packages/c3/58/fea732e48a7540035fe46d39e6fd77679f5810311d31da8661ce7a18210a/simplejson-3.19.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:212fce86a22188b0c7f53533b0f693ea9605c1a0f02c84c475a30616f55a744d", size = 74612 }, + { url = "https://files.pythonhosted.org/packages/ab/4d/15718f20cb0e3875b8af9597d6bb3bfbcf1383834b82b6385ee9ac0b72a9/simplejson-3.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d9e8f836688a8fabe6a6b41b334aa550a6823f7b4ac3d3712fc0ad8655be9a8", size = 143550 }, + { url = "https://files.pythonhosted.org/packages/93/44/815a4343774760f7a82459c8f6a4d8268b4b6d23f81e7b922a5e2ca79171/simplejson-3.19.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23228037dc5d41c36666384062904d74409a62f52283d9858fa12f4c22cffad1", size = 153284 }, + { url = "https://files.pythonhosted.org/packages/9d/52/d3202d9bba95444090d1c98e43da3c10907875babf63ed3c134d1b9437e3/simplejson-3.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0791f64fed7d4abad639491f8a6b1ba56d3c604eb94b50f8697359b92d983f36", size = 141518 }, + { url = "https://files.pythonhosted.org/packages/b7/d4/850948bcbcfe0b4a6c69dfde10e245d3a1ea45252f16a1e2308a3b06b1da/simplejson-3.19.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4f614581b61a26fbbba232a1391f6cee82bc26f2abbb6a0b44a9bba25c56a1c", size = 144688 }, + { url = "https://files.pythonhosted.org/packages/58/d2/b8dcb0a07d9cd54c47f9fe8733dbb83891d1efe4fc786d9dfc8781cc04f9/simplejson-3.19.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1df0aaf1cb787fdf34484ed4a1f0c545efd8811f6028623290fef1a53694e597", size = 144534 }, + { url = "https://files.pythonhosted.org/packages/a9/95/1e92d99039041f596e0923ec4f9153244acaf3830944dc69a7c11b23ceaa/simplejson-3.19.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:951095be8d4451a7182403354c22ec2de3e513e0cc40408b689af08d02611588", size = 146565 }, + { url = "https://files.pythonhosted.org/packages/21/04/c96aeb3a74031255e4cbcc0ca1b6ebfb5549902f0a065f06d65ce8447c0c/simplejson-3.19.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2a954b30810988feeabde843e3263bf187697e0eb5037396276db3612434049b", size = 155014 }, + { url = "https://files.pythonhosted.org/packages/b7/41/e28a28593afc4a75d8999d057bfb7c73a103e35f927e66f4bb92571787ae/simplejson-3.19.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c40df31a75de98db2cdfead6074d4449cd009e79f54c1ebe5e5f1f153c68ad20", size = 148092 }, + { url = "https://files.pythonhosted.org/packages/2b/82/1c81a3af06f937afb6d2e9d74a465c0e0ae6db444d1bf2a436ea26de1965/simplejson-3.19.3-cp311-cp311-win32.whl", hash = "sha256:7e2a098c21ad8924076a12b6c178965d88a0ad75d1de67e1afa0a66878f277a5", size = 73942 }, + { url = "https://files.pythonhosted.org/packages/65/be/d8ab9717f471be3c114f16abd8be21d9a6a0a09b9b49177d93d64d3717d9/simplejson-3.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:c9bedebdc5fdad48af8783022bae307746d54006b783007d1d3c38e10872a2c6", size = 75469 }, + { url = "https://files.pythonhosted.org/packages/20/15/513fea93fafbdd4993eacfcb762965b2ff3d29e618c029e2956174d68c4b/simplejson-3.19.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:66a0399e21c2112acacfebf3d832ebe2884f823b1c7e6d1363f2944f1db31a99", size = 92921 }, + { url = "https://files.pythonhosted.org/packages/a4/4f/998a907ae1a6c104dc0ee48aa248c2478490152808d34d8e07af57f396c3/simplejson-3.19.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6ef9383c5e05f445be60f1735c1816163c874c0b1ede8bb4390aff2ced34f333", size = 75311 }, + { url = "https://files.pythonhosted.org/packages/db/44/acd6122201e927451869d45952b9ab1d3025cdb5e61548d286d08fbccc08/simplejson-3.19.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:42e5acf80d4d971238d4df97811286a044d720693092b20a56d5e56b7dcc5d09", size = 74964 }, + { url = "https://files.pythonhosted.org/packages/27/ca/d0a1e8f16e1bbdc0b8c6d88166f45f565ed7285f53928cfef3b6ce78f14d/simplejson-3.19.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0b0efc7279d768db7c74d3d07f0b5c81280d16ae3fb14e9081dc903e8360771", size = 150106 }, + { url = "https://files.pythonhosted.org/packages/63/59/0554b78cf26c98e2b9cae3f44723bd72c2394e2afec1a14eedc6211f7187/simplejson-3.19.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0552eb06e7234da892e1d02365cd2b7b2b1f8233aa5aabdb2981587b7cc92ea0", size = 158347 }, + { url = "https://files.pythonhosted.org/packages/b2/fe/9f30890352e431e8508cc569912d3322147d3e7e4f321e48c0adfcb4c97d/simplejson-3.19.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf6a3b9a7d7191471b464fe38f684df10eb491ec9ea454003edb45a011ab187", size = 148456 }, + { url = "https://files.pythonhosted.org/packages/37/e3/663a09542ee021d4131162f7a164cb2e7f04ef48433a67591738afbf12ea/simplejson-3.19.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7017329ca8d4dca94ad5e59f496e5fc77630aecfc39df381ffc1d37fb6b25832", size = 152190 }, + { url = "https://files.pythonhosted.org/packages/31/20/4e0c4d35e10ff6465003bec304316d822a559a1c38c66ef6892ca199c207/simplejson-3.19.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:67a20641afebf4cfbcff50061f07daad1eace6e7b31d7622b6fa2c40d43900ba", size = 149846 }, + { url = "https://files.pythonhosted.org/packages/08/7a/46e2e072cac3987cbb05946f25167f0ad2fe536748e7405953fd6661a486/simplejson-3.19.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:dd6a7dabcc4c32daf601bc45e01b79175dde4b52548becea4f9545b0a4428169", size = 151714 }, + { url = "https://files.pythonhosted.org/packages/7f/7d/dbeeac10eb61d5d8858d0bb51121a21050d281dc83af4c557f86da28746c/simplejson-3.19.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:08f9b443a94e72dd02c87098c96886d35790e79e46b24e67accafbf13b73d43b", size = 158777 }, + { url = "https://files.pythonhosted.org/packages/fc/8f/a98bdbb799c6a4a884b5823db31785a96ba895b4b0f4d8ac345d6fe98bbf/simplejson-3.19.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fa97278ae6614346b5ca41a45a911f37a3261b57dbe4a00602048652c862c28b", size = 154230 }, + { url = "https://files.pythonhosted.org/packages/b1/db/852eebceb85f969ae40e06babed1a93d3bacb536f187d7a80ff5823a5979/simplejson-3.19.3-cp312-cp312-win32.whl", hash = "sha256:ef28c3b328d29b5e2756903aed888960bc5df39b4c2eab157ae212f70ed5bf74", size = 74002 }, + { url = "https://files.pythonhosted.org/packages/fe/68/9f0e5df0651cb79ef83cba1378765a00ee8038e6201cc82b8e7178a7778e/simplejson-3.19.3-cp312-cp312-win_amd64.whl", hash = "sha256:1e662336db50ad665777e6548b5076329a94a0c3d4a0472971c588b3ef27de3a", size = 75596 }, + { url = "https://files.pythonhosted.org/packages/93/3a/5896821ed543899fcb9c4256c7e71bb110048047349a00f42bc8b8fb379f/simplejson-3.19.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:0959e6cb62e3994b5a40e31047ff97ef5c4138875fae31659bead691bed55896", size = 92931 }, + { url = "https://files.pythonhosted.org/packages/39/15/5d33d269440912ee40d856db0c8be2b91aba7a219690ab01f86cb0edd590/simplejson-3.19.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7a7bfad839c624e139a4863007233a3f194e7c51551081f9789cba52e4da5167", size = 75318 }, + { url = "https://files.pythonhosted.org/packages/2a/8d/2e7483a2bf7ec53acf7e012bafbda79d7b34f90471dda8e424544a59d484/simplejson-3.19.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afab2f7f2486a866ff04d6d905e9386ca6a231379181a3838abce1f32fbdcc37", size = 74971 }, + { url = "https://files.pythonhosted.org/packages/4d/9d/9bdf34437c8834a7cf7246f85e9d5122e30579f512c10a0c2560e994294f/simplejson-3.19.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d00313681015ac498e1736b304446ee6d1c72c5b287cd196996dad84369998f7", size = 150112 }, + { url = "https://files.pythonhosted.org/packages/a7/e2/1f2ae2d89eaf85f6163c82150180aae5eaa18085cfaf892f8a57d4c51cbd/simplejson-3.19.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d936ae682d5b878af9d9eb4d8bb1fdd5e41275c8eb59ceddb0aeed857bb264a2", size = 158354 }, + { url = "https://files.pythonhosted.org/packages/60/83/26f610adf234c8492b3f30501e12f2271e67790f946c6898fe0c58aefe99/simplejson-3.19.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01c6657485393f2e9b8177c77a7634f13ebe70d5e6de150aae1677d91516ce6b", size = 148455 }, + { url = "https://files.pythonhosted.org/packages/b5/4b/109af50006af77133653c55b5b91b4bd2d579ff8254ce11216c0b75f911b/simplejson-3.19.3-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a6a750d3c7461b1c47cfc6bba8d9e57a455e7c5f80057d2a82f738040dd1129", size = 152191 }, + { url = "https://files.pythonhosted.org/packages/75/dc/108872a8825cbd99ae6f4334e0490ff1580367baf12198bcaf988f6820ba/simplejson-3.19.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ea7a4a998c87c5674a27089e022110a1a08a7753f21af3baf09efe9915c23c3c", size = 149954 }, + { url = "https://files.pythonhosted.org/packages/eb/be/deec1d947a5d0472276ab4a4d1a9378dc5ee27f3dc9e54d4f62ffbad7a08/simplejson-3.19.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6300680d83a399be2b8f3b0ef7ef90b35d2a29fe6e9c21438097e0938bbc1564", size = 151812 }, + { url = "https://files.pythonhosted.org/packages/e9/58/4ee130702d36b1551ef66e7587eefe56651f3669255bf748cd71691e2434/simplejson-3.19.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:ab69f811a660c362651ae395eba8ce84f84c944cea0df5718ea0ba9d1e4e7252", size = 158880 }, + { url = "https://files.pythonhosted.org/packages/0f/e1/59cc6a371b60f89e3498d9f4c8109f6b7359094d453f5fe80b2677b777b0/simplejson-3.19.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:256e09d0f94d9c3d177d9e95fd27a68c875a4baa2046633df387b86b652f5747", size = 154344 }, + { url = "https://files.pythonhosted.org/packages/79/45/1b36044670016f5cb25ebd92497427d2d1711ecb454d00f71eb9a00b77cc/simplejson-3.19.3-cp313-cp313-win32.whl", hash = "sha256:2c78293470313aefa9cfc5e3f75ca0635721fb016fb1121c1c5b0cb8cc74712a", size = 74002 }, + { url = "https://files.pythonhosted.org/packages/e2/58/b06226e6b0612f2b1fa13d5273551da259f894566b1eef32249ddfdcce44/simplejson-3.19.3-cp313-cp313-win_amd64.whl", hash = "sha256:3bbcdc438dc1683b35f7a8dc100960c721f922f9ede8127f63bed7dfded4c64c", size = 75599 }, + { url = "https://files.pythonhosted.org/packages/0d/e7/f9fafbd4f39793a20cc52e77bbd766f7384312526d402c382928dc7667f6/simplejson-3.19.3-py3-none-any.whl", hash = "sha256:49cc4c7b940d43bd12bf87ec63f28cbc4964fc4e12c031cc8cd01650f43eb94e", size = 57004 }, +] + [[package]] name = "six" version = "1.16.0" @@ -3760,6 +4368,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 }, ] +[[package]] +name = "smmap" +version = "5.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/88/04/b5bf6d21dc4041000ccba7eb17dd3055feb237e7ffc2c20d3fae3af62baa/smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62", size = 22291 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/a5/10f97f73544edcdef54409f1d839f6049a0d79df68adbc1ceb24d1aaca42/smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da", size = 24282 }, +] + [[package]] name = "sniffio" version = "1.3.1" @@ -3790,6 +4407,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/9c/93f7bc03ff03199074e81974cc148908ead60dcf189f68ba1761a0ee35cf/starlette-0.38.6-py3-none-any.whl", hash = "sha256:4517a1409e2e73ee4951214ba012052b9e16f60e90d73cfb06192c19203bbb05", size = 71451 }, ] +[[package]] +name = "swagger-spec-validator" +version = "3.0.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "importlib-resources" }, + { name = "jsonschema" }, + { name = "pyyaml" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e7/e9/d0a4a1e4ed6b4b805d5465affaeaa2d91ae08a8aae966f4bb7402e23ee37/swagger_spec_validator-3.0.4.tar.gz", hash = "sha256:637ac6d865270bfcd07df24605548e6e1f1d9c39adcfd855da37fa3fdebfed4b", size = 22355 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/ac/31ba87a959b19e640ebc18851438b82b5b66cef02ad31da7468d1d8bd625/swagger_spec_validator-3.0.4-py2.py3-none-any.whl", hash = "sha256:1a2a4f4f7076479ae7835d892dd53952ccca9414efa172c440c775cf0ac01f48", size = 28473 }, +] + [[package]] name = "sympy" version = "1.13.3" @@ -3813,11 +4445,32 @@ wheels = [ [[package]] name = "tenacity" -version = "9.0.0" +version = "8.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/4d/6a19536c50b849338fcbe9290d562b52cbdcf30d8963d3588a68a4107df1/tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78", size = 47309 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687", size = 28165 }, +] + +[[package]] +name = "thefuzz" +version = "0.22.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "rapidfuzz" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/81/4b/d3eb25831590d6d7d38c2f2e3561d3ba41d490dc89cd91d9e65e7c812508/thefuzz-0.22.1.tar.gz", hash = "sha256:7138039a7ecf540da323792d8592ef9902b1d79eb78c147d4f20664de79f3680", size = 19993 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/4f/1695e70ceb3604f19eda9908e289c687ea81c4fecef4d90a9d1d0f2f7ae9/thefuzz-0.22.1-py3-none-any.whl", hash = "sha256:59729b33556850b90e1093c4cf9e618af6f2e4c985df193fdf3c5b5cf02ca481", size = 8245 }, +] + +[[package]] +name = "threadpoolctl" +version = "3.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cd/94/91fccdb4b8110642462e653d5dcb27e7b674742ad68efd146367da7bdb10/tenacity-9.0.0.tar.gz", hash = "sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b", size = 47421 } +sdist = { url = "https://files.pythonhosted.org/packages/bd/55/b5148dcbf72f5cde221f8bfe3b6a540da7aa1842f6b491ad979a6c8b84af/threadpoolctl-3.5.0.tar.gz", hash = "sha256:082433502dd922bf738de0d8bcc4fdcbf0979ff44c42bd40f5af8a282f6fa107", size = 41936 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b6/cb/b86984bed139586d01532a587464b5805f12e397594f19f931c4c2fbfa61/tenacity-9.0.0-py3-none-any.whl", hash = "sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539", size = 28169 }, + { url = "https://files.pythonhosted.org/packages/4b/2c/ffbf7a134b9ab11a67b0cf0726453cedd9c5043a4fe7a35d1cefa9a1bcfb/threadpoolctl-3.5.0-py3-none-any.whl", hash = "sha256:56c1e26c150397e58c4926da8eeee87533b1e32bef131bd4bf6a2f45f3185467", size = 18414 }, ] [[package]] @@ -4028,6 +4681,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a8/2b/886d13e742e514f704c33c4caa7df0f3b89e5a25ef8db02aa9ca3d9535d5/typer-0.12.5-py3-none-any.whl", hash = "sha256:62fe4e471711b147e3365034133904df3e235698399bc4de2b36c8579298d52b", size = 47288 }, ] +[[package]] +name = "types-python-dateutil" +version = "2.9.0.20241003" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/f8/f6ee4c803a7beccffee21bb29a71573b39f7037c224843eff53e5308c16e/types-python-dateutil-2.9.0.20241003.tar.gz", hash = "sha256:58cb85449b2a56d6684e41aeefb4c4280631246a0da1a719bdbe6f3fb0317446", size = 9210 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/d6/ba5f61958f358028f2e2ba1b8e225b8e263053bd57d3a79e2d2db64c807b/types_python_dateutil-2.9.0.20241003-py3-none-any.whl", hash = "sha256:250e1d8e80e7bbc3a6c99b907762711d1a1cdd00e978ad39cb5940f6f0a87f3d", size = 9693 }, +] + [[package]] name = "typing-extensions" version = "4.12.2" @@ -4112,6 +4774,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f6/50/04e6712de68500220e81a496cd8b480015cbd041206cd08358882f400a78/unstructured_client-0.26.0-py3-none-any.whl", hash = "sha256:399b69441b5473ee4cdee38a0208573a4b646c02566e01eab1108066381a2914", size = 59673 }, ] +[[package]] +name = "uri-template" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/c7/0336f2bd0bcbada6ccef7aaa25e443c118a704f828a0620c6fa0207c1b64/uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", size = 21678 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363", size = 11140 }, +] + [[package]] name = "urllib3" version = "2.2.3" @@ -4292,6 +4963,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166 }, ] +[[package]] +name = "webcolors" +version = "24.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/f8/53150a5bda7e042840b14f0236e1c0a4819d403658e3d453237983addfac/webcolors-24.8.0.tar.gz", hash = "sha256:08b07af286a01bcd30d583a7acadf629583d1f79bfef27dd2c2c5c263817277d", size = 42392 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/33/12020ba99beaff91682b28dc0bbf0345bbc3244a4afbae7644e4fa348f23/webcolors-24.8.0-py3-none-any.whl", hash = "sha256:fc4c3b59358ada164552084a8ebee637c221e4059267d0f8325b3b560f6c7f0a", size = 15027 }, +] + [[package]] name = "websocket-client" version = "1.8.0"