diff --git a/.gitignore b/.gitignore index f8fd29897..760e3c59d 100644 --- a/.gitignore +++ b/.gitignore @@ -170,7 +170,6 @@ cython_debug/ # Database db test-db -!embedchain/embedchain/core/db/ .vscode .idea/ diff --git a/AGENTS.md b/AGENTS.md index 52d8ffc1e..7754b84a2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -33,7 +33,6 @@ This is a **polyglot monorepo** containing Python and TypeScript packages, CLIs, | `evaluation/` | Benchmarking framework — LOCOMO evals, experiment runner, score generation | | `examples/` | Sample projects — demo apps, Chrome extension, multi-agent patterns | | `cookbooks/` | Jupyter notebooks — customer support chatbot, AutoGen integration | -| `embedchain/` | Legacy Embedchain RAG framework (maintained separately, Poetry-based) | | `pr-reviews/` | Pull request review materials | | `scripts/` | Repo-wide utility scripts (e.g., `check-llms-txt-coverage.py` for docs/llms.txt sync) | @@ -330,7 +329,7 @@ make run-openai # OpenAI comparison - Root SDK: line length **120** - Python CLI: line length **100** with extended rule set (UP, B, SIM, RUF) - **isort** with `profile = "black"` for import sorting. -- Ruff excludes `embedchain/` and `openmemory/` from root config. +- Ruff excludes `openmemory/` from root config. ### TypeScript Conventions @@ -414,7 +413,6 @@ To add a new LLM, embedding, vector store, or reranker provider: | Python CLI | `cli-python-ci.yml` | Push to `cli/python/`, PRs, manual | Ruff lint + pytest + hatch build on Python 3.10, 3.11, 3.12 | | Node CLI | `cli-node-ci.yml` | Push to `cli/node/`, PRs, manual | Biome lint + tsc + vitest + tsup build on Node 20, 22 | | OpenClaw | `openclaw-checks.yml` | Push to `openclaw/`, PRs, manual | tsc + vitest (with Codecov) + tsup build on Node 20, 22 | -| Embedchain | `ci.yml` (shared) | PRs on `embedchain/` | Ruff + pytest + coverage on Python 3.9–3.12 | ### CD Workflows (automated publishing) @@ -576,7 +574,6 @@ N/A - Modify CI/CD workflows without explicit approval. - Add new Python dependencies to the core `dependencies` list in `pyproject.toml` without discussion — use optional dependency groups instead. - Commit `.env` files, API keys, or credentials. -- Modify `embedchain/` unless specifically working on that package — it has its own build system (Poetry). - Skip pre-commit hooks. - Use npm or yarn in TypeScript packages — this repo uses pnpm exclusively. - Use `require()` for imports in TypeScript — use ES module `import` syntax. diff --git a/embedchain/CITATION.cff b/embedchain/CITATION.cff deleted file mode 100644 index 8b93297cd..000000000 --- a/embedchain/CITATION.cff +++ /dev/null @@ -1,8 +0,0 @@ -cff-version: 1.2.0 -message: "If you use this software, please cite it as below." -authors: -- family-names: "Singh" - given-names: "Taranjeet" -title: "Embedchain" -date-released: 2023-06-20 -url: "https://github.com/embedchain/embedchain" \ No newline at end of file diff --git a/embedchain/CONTRIBUTING.md b/embedchain/CONTRIBUTING.md deleted file mode 100644 index a0d7c12e8..000000000 --- a/embedchain/CONTRIBUTING.md +++ /dev/null @@ -1,76 +0,0 @@ -# Contributing to embedchain - -Let us make contribution easy, collaborative and fun. - -## Submit your Contribution through PR - -To make a contribution, follow these steps: - -1. Fork and clone this repository -2. Do the changes on your fork with dedicated feature branch `feature/f1` -3. If you modified the code (new feature or bug-fix), please add tests for it -4. Include proper documentation / docstring and examples to run the feature -5. Check the linting -6. Ensure that all tests pass -7. Submit a pull request - -For more details about pull requests, please read [GitHub's guides](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request). - - -### 📦 Package manager - -We use `poetry` as our package manager. You can install poetry by following the instructions [here](https://python-poetry.org/docs/#installation). - -Please DO NOT use pip or conda to install the dependencies. Instead, use poetry: - -```bash -make install_all - -#activate - -poetry shell -``` - -### 📌 Pre-commit - -To ensure our standards, make sure to install pre-commit before starting to contribute. - -```bash -pre-commit install -``` - -### 🧹 Linting - -We use `ruff` to lint our code. You can run the linter by running the following command: - -```bash -make lint -``` - -Make sure that the linter does not report any errors or warnings before submitting a pull request. - -### Code Formatting with `black` - -We use `black` to reformat the code by running the following command: - -```bash -make format -``` - -### 🧪 Testing - -We use `pytest` to test our code. You can run the tests by running the following command: - -```bash -poetry run pytest -``` - - -Several packages have been removed from Poetry to make the package lighter. Therefore, it is recommended to run `make install_all` to install the remaining packages and ensure all tests pass. - - -Make sure that all tests pass before submitting a pull request. - -## 🚀 Release Process - -At the moment, the release process is manual. We try to make frequent releases. Usually, we release a new version when we have a new feature or bugfix. A developer with admin rights to the repository will create a new release on GitHub, and then publish the new version to PyPI. diff --git a/embedchain/LICENSE b/embedchain/LICENSE deleted file mode 100644 index d20d5102c..000000000 --- a/embedchain/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [2023] [Taranjeet Singh] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/embedchain/Makefile b/embedchain/Makefile deleted file mode 100644 index f9ecc81fc..000000000 --- a/embedchain/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# Variables -PYTHON := python3 -PIP := $(PYTHON) -m pip -PROJECT_NAME := embedchain - -# Targets -.PHONY: install format lint clean test ci_lint ci_test coverage - -install: - poetry install - -# TODO: use a more efficient way to install these packages -install_all: - poetry install --all-extras - poetry run pip install ruff==0.6.9 pinecone-text pinecone-client langchain-anthropic "unstructured[local-inference, all-docs]" ollama langchain_together==0.1.3 \ - langchain_cohere==0.1.5 deepgram-sdk==3.2.7 langchain-huggingface psutil clarifai==10.0.1 flask==2.3.3 twilio==8.5.0 fastapi-poe==0.0.16 discord==2.3.2 \ - slack-sdk==3.21.3 huggingface_hub==0.23.0 gitpython==3.1.38 yt_dlp==2023.11.14 PyGithub==1.59.1 feedparser==6.0.10 newspaper3k==0.2.8 listparser==0.19 \ - modal==0.56.4329 dropbox==11.36.2 boto3==1.34.20 youtube-transcript-api==0.6.1 pytube==15.0.0 beautifulsoup4==4.12.3 - -install_es: - poetry install --extras elasticsearch - -install_opensearch: - poetry install --extras opensearch - -install_milvus: - poetry install --extras milvus - -shell: - poetry shell - -py_shell: - poetry run python - -format: - $(PYTHON) -m black . - $(PYTHON) -m isort . - -clean: - rm -rf dist build *.egg-info - -lint: - poetry run ruff . - -build: - poetry build - -publish: - poetry publish - -# for example: make test file=tests/test_factory.py -test: - poetry run pytest $(file) - -coverage: - poetry run pytest --cov=$(PROJECT_NAME) --cov-report=xml diff --git a/embedchain/README.md b/embedchain/README.md deleted file mode 100644 index 8b072ed87..000000000 --- a/embedchain/README.md +++ /dev/null @@ -1,125 +0,0 @@ -

- Embedchain Logo -

- -

- - PyPI - - - Downloads - - - Slack - - - Discord - - - Twitter - - - Open in Colab - - - codecov - -

- -
- -## What is Embedchain? - -Embedchain is an Open Source Framework for personalizing LLM responses. It makes it easy to create and deploy personalized AI apps. At its core, Embedchain follows the design principle of being *"Conventional but Configurable"* to serve both software engineers and machine learning engineers. - -Embedchain streamlines the creation of personalized LLM applications, offering a seamless process for managing various types of unstructured data. It efficiently segments data into manageable chunks, generates relevant embeddings, and stores them in a vector database for optimized retrieval. With a suite of diverse APIs, it enables users to extract contextual information, find precise answers, or engage in interactive chat conversations, all tailored to their own data. - -## 🔧 Quick install - -### Python API - -```bash -pip install embedchain -``` - -## ✨ Live demo - -Checkout the [Chat with PDF](https://embedchain.ai/demo/chat-pdf) live demo we created using Embedchain. You can find the source code [here](https://github.com/mem0ai/mem0/tree/main/embedchain/examples/chat-pdf). - -## 🔍 Usage - - -

- Embedchain Demo -

- -For example, you can create an Elon Musk bot using the following code: - -```python -import os -from embedchain import App - -# Create a bot instance -os.environ["OPENAI_API_KEY"] = "" -app = App() - -# Embed online resources -app.add("https://en.wikipedia.org/wiki/Elon_Musk") -app.add("https://www.forbes.com/profile/elon-musk") - -# Query the app -app.query("How many companies does Elon Musk run and name those?") -# Answer: Elon Musk currently runs several companies. As of my knowledge, he is the CEO and lead designer of SpaceX, the CEO and product architect of Tesla, Inc., the CEO and founder of Neuralink, and the CEO and founder of The Boring Company. However, please note that this information may change over time, so it's always good to verify the latest updates. -``` - -You can also try it in your browser with Google Colab: - -[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/17ON1LPonnXAtLaZEebnOktstB_1cJJmh?usp=sharing) - -## 📖 Documentation -Comprehensive guides and API documentation are available to help you get the most out of Embedchain: - -- [Introduction](https://docs.embedchain.ai/get-started/introduction#what-is-embedchain) -- [Getting Started](https://docs.embedchain.ai/get-started/quickstart) -- [Examples](https://docs.embedchain.ai/examples) -- [Supported data types](https://docs.embedchain.ai/components/data-sources/overview) - -## 🔗 Join the Community - -* Connect with fellow developers by joining our [Slack Community](https://embedchain.ai/slack) or [Discord Community](https://embedchain.ai/discord). - -* Dive into [GitHub Discussions](https://github.com/embedchain/embedchain/discussions), ask questions, or share your experiences. - -## 🤝 Schedule a 1-on-1 Session - -Book a [1-on-1 Session](https://cal.com/taranjeetio/ec) with the founders, to discuss any issues, provide feedback, or explore how we can improve Embedchain for you. - -## 🌐 Contributing - -Contributions are welcome! Please check out the issues on the repository, and feel free to open a pull request. -For more information, please see the [contributing guidelines](CONTRIBUTING.md). - -For more reference, please go through [Development Guide](https://docs.embedchain.ai/contribution/dev) and [Documentation Guide](https://docs.embedchain.ai/contribution/docs). - - - - - -## Anonymous Telemetry - -We collect anonymous usage metrics to enhance our package's quality and user experience. This includes data like feature usage frequency and system info, but never personal details. The data helps us prioritize improvements and ensure compatibility. If you wish to opt-out, set the environment variable `EC_TELEMETRY=false`. We prioritize data security and don't share this data externally. - -## Citation - -If you utilize this repository, please consider citing it with: - -``` -@misc{embedchain, - author = {Taranjeet Singh, Deshraj Yadav}, - title = {Embedchain: The Open Source RAG Framework}, - year = {2023}, - publisher = {GitHub}, - journal = {GitHub repository}, - howpublished = {\url{https://github.com/embedchain/embedchain}}, -} -``` diff --git a/embedchain/configs/anthropic.yaml b/embedchain/configs/anthropic.yaml deleted file mode 100644 index 395125f99..000000000 --- a/embedchain/configs/anthropic.yaml +++ /dev/null @@ -1,8 +0,0 @@ -llm: - provider: anthropic - config: - model: 'claude-instant-1' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false diff --git a/embedchain/configs/aws_bedrock.yaml b/embedchain/configs/aws_bedrock.yaml deleted file mode 100644 index 824ab0fff..000000000 --- a/embedchain/configs/aws_bedrock.yaml +++ /dev/null @@ -1,15 +0,0 @@ -llm: - provider: aws_bedrock - config: - model: amazon.titan-text-express-v1 - deployment_name: your_llm_deployment_name - temperature: 0.5 - max_tokens: 8192 - top_p: 1 - stream: false - -embedder:: - provider: aws_bedrock - config: - model: amazon.titan-embed-text-v2:0 - deployment_name: you_embedding_model_deployment_name \ No newline at end of file diff --git a/embedchain/configs/azure_openai.yaml b/embedchain/configs/azure_openai.yaml deleted file mode 100644 index 50eaff0c8..000000000 --- a/embedchain/configs/azure_openai.yaml +++ /dev/null @@ -1,19 +0,0 @@ -app: - config: - id: azure-openai-app - -llm: - provider: azure_openai - config: - model: gpt-35-turbo - deployment_name: your_llm_deployment_name - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -embedder: - provider: azure_openai - config: - model: text-embedding-ada-002 - deployment_name: you_embedding_model_deployment_name diff --git a/embedchain/configs/chroma.yaml b/embedchain/configs/chroma.yaml deleted file mode 100644 index 142eb05fc..000000000 --- a/embedchain/configs/chroma.yaml +++ /dev/null @@ -1,24 +0,0 @@ -app: - config: - id: 'my-app' - -llm: - provider: openai - config: - model: 'gpt-4o-mini' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -vectordb: - provider: chroma - config: - collection_name: 'my-app' - dir: db - allow_reset: true - -embedder: - provider: openai - config: - model: 'text-embedding-ada-002' diff --git a/embedchain/configs/chunker.yaml b/embedchain/configs/chunker.yaml deleted file mode 100644 index 63cf3f82c..000000000 --- a/embedchain/configs/chunker.yaml +++ /dev/null @@ -1,4 +0,0 @@ -chunker: - chunk_size: 100 - chunk_overlap: 20 - length_function: 'len' diff --git a/embedchain/configs/clarifai.yaml b/embedchain/configs/clarifai.yaml deleted file mode 100644 index 0c52ba007..000000000 --- a/embedchain/configs/clarifai.yaml +++ /dev/null @@ -1,12 +0,0 @@ -llm: - provider: clarifai - config: - model: "https://clarifai.com/mistralai/completion/models/mistral-7B-Instruct" - model_kwargs: - temperature: 0.5 - max_tokens: 1000 - -embedder: - provider: clarifai - config: - model: "https://clarifai.com/clarifai/main/models/BAAI-bge-base-en-v15" diff --git a/embedchain/configs/cohere.yaml b/embedchain/configs/cohere.yaml deleted file mode 100644 index 0edd4e8fd..000000000 --- a/embedchain/configs/cohere.yaml +++ /dev/null @@ -1,7 +0,0 @@ -llm: - provider: cohere - config: - model: large - temperature: 0.5 - max_tokens: 1000 - top_p: 1 diff --git a/embedchain/configs/full-stack.yaml b/embedchain/configs/full-stack.yaml deleted file mode 100644 index 978722eac..000000000 --- a/embedchain/configs/full-stack.yaml +++ /dev/null @@ -1,40 +0,0 @@ -app: - config: - id: 'full-stack-app' - -chunker: - chunk_size: 100 - chunk_overlap: 20 - length_function: 'len' - -llm: - provider: openai - config: - model: 'gpt-4o-mini' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - prompt: | - Use the following pieces of context to answer the query at the end. - If you don't know the answer, just say that you don't know, don't try to make up an answer. - - $context - - Query: $query - - Helpful Answer: - system_prompt: | - Act as William Shakespeare. Answer the following questions in the style of William Shakespeare. - -vectordb: - provider: chroma - config: - collection_name: 'my-collection-name' - dir: db - allow_reset: true - -embedder: - provider: openai - config: - model: 'text-embedding-ada-002' diff --git a/embedchain/configs/google.yaml b/embedchain/configs/google.yaml deleted file mode 100644 index 4f6a46553..000000000 --- a/embedchain/configs/google.yaml +++ /dev/null @@ -1,13 +0,0 @@ -llm: - provider: google - config: - model: gemini-pro - max_tokens: 1000 - temperature: 0.9 - top_p: 1.0 - stream: false - -embedder: - provider: google - config: - model: models/embedding-001 diff --git a/embedchain/configs/gpt4.yaml b/embedchain/configs/gpt4.yaml deleted file mode 100644 index e06c60de6..000000000 --- a/embedchain/configs/gpt4.yaml +++ /dev/null @@ -1,8 +0,0 @@ -llm: - provider: openai - config: - model: 'gpt-4' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false \ No newline at end of file diff --git a/embedchain/configs/gpt4all.yaml b/embedchain/configs/gpt4all.yaml deleted file mode 100644 index 048239334..000000000 --- a/embedchain/configs/gpt4all.yaml +++ /dev/null @@ -1,11 +0,0 @@ -llm: - provider: gpt4all - config: - model: 'orca-mini-3b-gguf2-q4_0.gguf' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -embedder: - provider: gpt4all diff --git a/embedchain/configs/huggingface.yaml b/embedchain/configs/huggingface.yaml deleted file mode 100644 index 508c9d778..000000000 --- a/embedchain/configs/huggingface.yaml +++ /dev/null @@ -1,8 +0,0 @@ -llm: - provider: huggingface - config: - model: 'google/flan-t5-xxl' - temperature: 0.5 - max_tokens: 1000 - top_p: 0.5 - stream: false diff --git a/embedchain/configs/jina.yaml b/embedchain/configs/jina.yaml deleted file mode 100644 index 11627059b..000000000 --- a/embedchain/configs/jina.yaml +++ /dev/null @@ -1,7 +0,0 @@ -llm: - provider: jina - config: - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false diff --git a/embedchain/configs/llama2.yaml b/embedchain/configs/llama2.yaml deleted file mode 100644 index 61b3b9253..000000000 --- a/embedchain/configs/llama2.yaml +++ /dev/null @@ -1,8 +0,0 @@ -llm: - provider: llama2 - config: - model: 'a16z-infra/llama13b-v2-chat:df7690f1994d94e96ad9d568eac121aecf50684a0b0963b25a41cc40061269e5' - temperature: 0.5 - max_tokens: 1000 - top_p: 0.5 - stream: false diff --git a/embedchain/configs/ollama.yaml b/embedchain/configs/ollama.yaml deleted file mode 100644 index 7ec5def54..000000000 --- a/embedchain/configs/ollama.yaml +++ /dev/null @@ -1,14 +0,0 @@ -llm: - provider: ollama - config: - model: 'llama2' - temperature: 0.5 - top_p: 1 - stream: true - base_url: http://localhost:11434 - -embedder: - provider: ollama - config: - model: 'mxbai-embed-large:latest' - base_url: http://localhost:11434 diff --git a/embedchain/configs/opensearch.yaml b/embedchain/configs/opensearch.yaml deleted file mode 100644 index 94a27b29f..000000000 --- a/embedchain/configs/opensearch.yaml +++ /dev/null @@ -1,33 +0,0 @@ -app: - config: - id: 'my-app' - log_level: 'WARNING' - collect_metrics: true - collection_name: 'my-app' - -llm: - provider: openai - config: - model: 'gpt-4o-mini' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -vectordb: - provider: opensearch - config: - opensearch_url: 'https://localhost:9200' - http_auth: - - admin - - admin - vector_dimension: 1536 - collection_name: 'my-app' - use_ssl: false - verify_certs: false - -embedder: - provider: openai - config: - model: 'text-embedding-ada-002' - deployment_name: 'my-app' diff --git a/embedchain/configs/opensource.yaml b/embedchain/configs/opensource.yaml deleted file mode 100644 index e2d40c135..000000000 --- a/embedchain/configs/opensource.yaml +++ /dev/null @@ -1,25 +0,0 @@ -app: - config: - id: 'open-source-app' - collect_metrics: false - -llm: - provider: gpt4all - config: - model: 'orca-mini-3b-gguf2-q4_0.gguf' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -vectordb: - provider: chroma - config: - collection_name: 'open-source-app' - dir: db - allow_reset: true - -embedder: - provider: gpt4all - config: - deployment_name: 'test-deployment' diff --git a/embedchain/configs/pinecone.yaml b/embedchain/configs/pinecone.yaml deleted file mode 100644 index 24e33c11a..000000000 --- a/embedchain/configs/pinecone.yaml +++ /dev/null @@ -1,6 +0,0 @@ -vectordb: - provider: pinecone - config: - metric: cosine - vector_dimension: 1536 - collection_name: my-pinecone-index diff --git a/embedchain/configs/pipeline.yaml b/embedchain/configs/pipeline.yaml deleted file mode 100644 index e34866716..000000000 --- a/embedchain/configs/pipeline.yaml +++ /dev/null @@ -1,26 +0,0 @@ -pipeline: - config: - name: Example pipeline - id: pipeline-1 # Make sure that id is different every time you create a new pipeline - -vectordb: - provider: chroma - config: - collection_name: pipeline-1 - dir: db - allow_reset: true - -llm: - provider: gpt4all - config: - model: 'orca-mini-3b-gguf2-q4_0.gguf' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -embedding_model: - provider: gpt4all - config: - model: 'all-MiniLM-L6-v2' - deployment_name: null diff --git a/embedchain/configs/together.yaml b/embedchain/configs/together.yaml deleted file mode 100644 index b19bc07ff..000000000 --- a/embedchain/configs/together.yaml +++ /dev/null @@ -1,6 +0,0 @@ -llm: - provider: together - config: - model: mistralai/Mixtral-8x7B-Instruct-v0.1 - temperature: 0.5 - max_tokens: 1000 diff --git a/embedchain/configs/vertexai.yaml b/embedchain/configs/vertexai.yaml deleted file mode 100644 index f303654c0..000000000 --- a/embedchain/configs/vertexai.yaml +++ /dev/null @@ -1,6 +0,0 @@ -llm: - provider: vertexai - config: - model: 'chat-bison' - temperature: 0.5 - top_p: 0.5 diff --git a/embedchain/configs/vllm.yaml b/embedchain/configs/vllm.yaml deleted file mode 100644 index 536a589a1..000000000 --- a/embedchain/configs/vllm.yaml +++ /dev/null @@ -1,14 +0,0 @@ -llm: - provider: vllm - config: - model: 'meta-llama/Llama-2-70b-hf' - temperature: 0.5 - top_p: 1 - top_k: 10 - stream: true - trust_remote_code: true - -embedder: - provider: huggingface - config: - model: 'BAAI/bge-small-en-v1.5' diff --git a/embedchain/configs/weaviate.yaml b/embedchain/configs/weaviate.yaml deleted file mode 100644 index a27623ab9..000000000 --- a/embedchain/configs/weaviate.yaml +++ /dev/null @@ -1,4 +0,0 @@ -vectordb: - provider: weaviate - config: - collection_name: my_weaviate_index diff --git a/embedchain/docs/Makefile b/embedchain/docs/Makefile deleted file mode 100644 index 0db640d0e..000000000 --- a/embedchain/docs/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -install: - npm i -g mintlify - -run_local: - mintlify dev - -troubleshoot: - mintlify install - -.PHONY: install run_local troubleshoot diff --git a/embedchain/docs/README.md b/embedchain/docs/README.md deleted file mode 100644 index e322686dc..000000000 --- a/embedchain/docs/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Contributing to embedchain docs - - -### 👩‍💻 Development - -Install the [Mintlify CLI](https://www.npmjs.com/package/mintlify) to preview the documentation changes locally. To install, use the following command - -``` -npm i -g mintlify -``` - -Run the following command at the root of your documentation (where mint.json is) - -``` -mintlify dev -``` - -### 😎 Publishing Changes - -Changes will be deployed to production automatically after your PR is merged to the main branch. - -#### Troubleshooting - -- Mintlify dev isn't running - Run `mintlify install` it'll re-install dependencies. -- Page loads as a 404 - Make sure you are running in a folder with `mint.json` diff --git a/embedchain/docs/_snippets/get-help.mdx b/embedchain/docs/_snippets/get-help.mdx deleted file mode 100644 index 6f57e5ce5..000000000 --- a/embedchain/docs/_snippets/get-help.mdx +++ /dev/null @@ -1,11 +0,0 @@ - - - Schedule a call - - - Join our slack community - - - Join our discord community - - diff --git a/embedchain/docs/_snippets/missing-data-source-tip.mdx b/embedchain/docs/_snippets/missing-data-source-tip.mdx deleted file mode 100644 index b0e189553..000000000 --- a/embedchain/docs/_snippets/missing-data-source-tip.mdx +++ /dev/null @@ -1,19 +0,0 @@ -

If you can't find the specific data source, please feel free to request through one of the following channels and help us prioritize.

- - - - Fill out this form - - - Let us know on our slack community - - - Let us know on discord community - - - Open an issue on our GitHub - - - Schedule a call with Embedchain founder - - diff --git a/embedchain/docs/_snippets/missing-llm-tip.mdx b/embedchain/docs/_snippets/missing-llm-tip.mdx deleted file mode 100644 index 7d2782d38..000000000 --- a/embedchain/docs/_snippets/missing-llm-tip.mdx +++ /dev/null @@ -1,16 +0,0 @@ -

If you can't find the specific LLM you need, no need to fret. We're continuously expanding our support for additional LLMs, and you can help us prioritize by opening an issue on our GitHub or simply reaching out to us on our Slack or Discord community.

- - - - Let us know on our slack community - - - Let us know on discord community - - - Open an issue on our GitHub - - - Schedule a call with Embedchain founder - - diff --git a/embedchain/docs/_snippets/missing-vector-db-tip.mdx b/embedchain/docs/_snippets/missing-vector-db-tip.mdx deleted file mode 100644 index 2edbbe4b0..000000000 --- a/embedchain/docs/_snippets/missing-vector-db-tip.mdx +++ /dev/null @@ -1,18 +0,0 @@ - - -

If you can't find specific feature or run into issues, please feel free to reach out through one of the following channels.

- - - - Let us know on our slack community - - - Let us know on discord community - - - Open an issue on our GitHub - - - Schedule a call with Embedchain founder - - diff --git a/embedchain/docs/api-reference/advanced/configuration.mdx b/embedchain/docs/api-reference/advanced/configuration.mdx deleted file mode 100644 index 568ea567e..000000000 --- a/embedchain/docs/api-reference/advanced/configuration.mdx +++ /dev/null @@ -1,273 +0,0 @@ ---- -title: 'Custom configurations' ---- - -Embedchain offers several configuration options for your LLM, vector database, and embedding model. All of these configuration options are optional and have sane defaults. - -You can configure different components of your app (`llm`, `embedding model`, or `vector database`) through a simple yaml configuration that Embedchain offers. Here is a generic full-stack example of the yaml config: - - - -Embedchain applications are configurable using YAML file, JSON file or by directly passing the config dictionary. Checkout the [docs here](/api-reference/app/overview#usage) on how to use other formats. - - - -```yaml config.yaml -app: - config: - name: 'full-stack-app' - -llm: - provider: openai - config: - model: 'gpt-4o-mini' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - api_key: sk-xxx - model_kwargs: - response_format: - type: json_object - api_version: 2024-02-01 - http_client_proxies: http://testproxy.mem0.net:8000 - prompt: | - Use the following pieces of context to answer the query at the end. - If you don't know the answer, just say that you don't know, don't try to make up an answer. - - $context - - Query: $query - - Helpful Answer: - system_prompt: | - Act as William Shakespeare. Answer the following questions in the style of William Shakespeare. - -vectordb: - provider: chroma - config: - collection_name: 'full-stack-app' - dir: db - allow_reset: true - -embedder: - provider: openai - config: - model: 'text-embedding-ada-002' - api_key: sk-xxx - http_client_proxies: http://testproxy.mem0.net:8000 - -chunker: - chunk_size: 2000 - chunk_overlap: 100 - length_function: 'len' - min_chunk_size: 0 - -cache: - similarity_evaluation: - strategy: distance - max_distance: 1.0 - config: - similarity_threshold: 0.8 - auto_flush: 50 - -memory: - top_k: 10 -``` - -```json config.json -{ - "app": { - "config": { - "name": "full-stack-app" - } - }, - "llm": { - "provider": "openai", - "config": { - "model": "gpt-4o-mini", - "temperature": 0.5, - "max_tokens": 1000, - "top_p": 1, - "stream": false, - "prompt": "Use the following pieces of context to answer the query at the end.\nIf you don't know the answer, just say that you don't know, don't try to make up an answer.\n$context\n\nQuery: $query\n\nHelpful Answer:", - "system_prompt": "Act as William Shakespeare. Answer the following questions in the style of William Shakespeare.", - "api_key": "sk-xxx", - "model_kwargs": {"response_format": {"type": "json_object"}}, - "api_version": "2024-02-01", - "http_client_proxies": "http://testproxy.mem0.net:8000" - } - }, - "vectordb": { - "provider": "chroma", - "config": { - "collection_name": "full-stack-app", - "dir": "db", - "allow_reset": true - } - }, - "embedder": { - "provider": "openai", - "config": { - "model": "text-embedding-ada-002", - "api_key": "sk-xxx", - "http_client_proxies": "http://testproxy.mem0.net:8000" - } - }, - "chunker": { - "chunk_size": 2000, - "chunk_overlap": 100, - "length_function": "len", - "min_chunk_size": 0 - }, - "cache": { - "similarity_evaluation": { - "strategy": "distance", - "max_distance": 1.0 - }, - "config": { - "similarity_threshold": 0.8, - "auto_flush": 50 - } - }, - "memory": { - "top_k": 10 - } -} -``` - -```python config.py -config = { - 'app': { - 'config': { - 'name': 'full-stack-app' - } - }, - 'llm': { - 'provider': 'openai', - 'config': { - 'model': 'gpt-4o-mini', - 'temperature': 0.5, - 'max_tokens': 1000, - 'top_p': 1, - 'stream': False, - 'prompt': ( - "Use the following pieces of context to answer the query at the end.\n" - "If you don't know the answer, just say that you don't know, don't try to make up an answer.\n" - "$context\n\nQuery: $query\n\nHelpful Answer:" - ), - 'system_prompt': ( - "Act as William Shakespeare. Answer the following questions in the style of William Shakespeare." - ), - 'api_key': 'sk-xxx', - "model_kwargs": {"response_format": {"type": "json_object"}}, - "http_client_proxies": "http://testproxy.mem0.net:8000", - } - }, - 'vectordb': { - 'provider': 'chroma', - 'config': { - 'collection_name': 'full-stack-app', - 'dir': 'db', - 'allow_reset': True - } - }, - 'embedder': { - 'provider': 'openai', - 'config': { - 'model': 'text-embedding-ada-002', - 'api_key': 'sk-xxx', - "http_client_proxies": "http://testproxy.mem0.net:8000", - } - }, - 'chunker': { - 'chunk_size': 2000, - 'chunk_overlap': 100, - 'length_function': 'len', - 'min_chunk_size': 0 - }, - 'cache': { - 'similarity_evaluation': { - 'strategy': 'distance', - 'max_distance': 1.0, - }, - 'config': { - 'similarity_threshold': 0.8, - 'auto_flush': 50, - }, - }, - 'memory': { - 'top_k': 10, - }, -} -``` - - -Alright, let's dive into what each key means in the yaml config above: - -1. `app` Section: - - `config`: - - `name` (String): The name of your full-stack application. - - `id` (String): The id of your full-stack application. - Only use this to reload already created apps. We recommend users not to create their own ids. - - `collect_metrics` (Boolean): Indicates whether metrics should be collected for the app, defaults to `True` - - `log_level` (String): The log level for the app, defaults to `WARNING` -2. `llm` Section: - - `provider` (String): The provider for the language model, which is set to 'openai'. You can find the full list of llm providers in [our docs](/components/llms). - - `config`: - - `model` (String): The specific model being used, 'gpt-4o-mini'. - - `temperature` (Float): Controls the randomness of the model's output. A higher value (closer to 1) makes the output more random. - - `max_tokens` (Integer): Controls how many tokens are used in the response. - - `top_p` (Float): Controls the diversity of word selection. A higher value (closer to 1) makes word selection more diverse. - - `stream` (Boolean): Controls if the response is streamed back to the user (set to false). - - `online` (Boolean): Controls whether to use internet to get more context for answering query (set to false). - - `token_usage` (Boolean): Controls whether to use token usage for the querying models (set to false). - - `prompt` (String): A prompt for the model to follow when generating responses, requires `$context` and `$query` variables. - - `system_prompt` (String): A system prompt for the model to follow when generating responses, in this case, it's set to the style of William Shakespeare. - - `number_documents` (Integer): Number of documents to pull from the vectordb as context, defaults to 1 - - `api_key` (String): The API key for the language model. - - `model_kwargs` (Dict): Keyword arguments to pass to the language model. Used for `aws_bedrock` provider, since it requires different arguments for each model. - - `http_client_proxies` (Dict | String): The proxy server settings used to create `self.http_client` using `httpx.Client(proxies=http_client_proxies)` - - `http_async_client_proxies` (Dict | String): The proxy server settings for async calls used to create `self.http_async_client` using `httpx.AsyncClient(proxies=http_async_client_proxies)` -3. `vectordb` Section: - - `provider` (String): The provider for the vector database, set to 'chroma'. You can find the full list of vector database providers in [our docs](/components/vector-databases). - - `config`: - - `collection_name` (String): The initial collection name for the vectordb, set to 'full-stack-app'. - - `dir` (String): The directory for the local database, set to 'db'. - - `allow_reset` (Boolean): Indicates whether resetting the vectordb is allowed, set to true. - - `batch_size` (Integer): The batch size for docs insertion in vectordb, defaults to `100` - We recommend you to checkout vectordb specific config [here](https://docs.embedchain.ai/components/vector-databases) -4. `embedder` Section: - - `provider` (String): The provider for the embedder, set to 'openai'. You can find the full list of embedding model providers in [our docs](/components/embedding-models). - - `config`: - - `model` (String): The specific model used for text embedding, 'text-embedding-ada-002'. - - `vector_dimension` (Integer): The vector dimension of the embedding model. [Defaults](https://github.com/embedchain/embedchain/blob/main/embedchain/models/vector_dimensions.py) - - `api_key` (String): The API key for the embedding model. - - `endpoint` (String): The endpoint for the HuggingFace embedding model. - - `deployment_name` (String): The deployment name for the embedding model. - - `title` (String): The title for the embedding model for Google Embedder. - - `task_type` (String): The task type for the embedding model for Google Embedder. - - `model_kwargs` (Dict): Used to pass extra arguments to embedders. - - `http_client_proxies` (Dict | String): The proxy server settings used to create `self.http_client` using `httpx.Client(proxies=http_client_proxies)` - - `http_async_client_proxies` (Dict | String): The proxy server settings for async calls used to create `self.http_async_client` using `httpx.AsyncClient(proxies=http_async_client_proxies)` -5. `chunker` Section: - - `chunk_size` (Integer): The size of each chunk of text that is sent to the language model. - - `chunk_overlap` (Integer): The amount of overlap between each chunk of text. - - `length_function` (String): The function used to calculate the length of each chunk of text. In this case, it's set to 'len'. You can also use any function import directly as a string here. - - `min_chunk_size` (Integer): The minimum size of each chunk of text that is sent to the language model. Must be less than `chunk_size`, and greater than `chunk_overlap`. -6. `cache` Section: (Optional) - - `similarity_evaluation` (Optional): The config for similarity evaluation strategy. If not provided, the default `distance` based similarity evaluation strategy is used. - - `strategy` (String): The strategy to use for similarity evaluation. Currently, only `distance` and `exact` based similarity evaluation is supported. Defaults to `distance`. - - `max_distance` (Float): The bound of maximum distance. Defaults to `1.0`. - - `positive` (Boolean): If the larger distance indicates more similar of two entities, set it `True`, otherwise `False`. Defaults to `False`. - - `config` (Optional): The config for initializing the cache. If not provided, sensible default values are used as mentioned below. - - `similarity_threshold` (Float): The threshold for similarity evaluation. Defaults to `0.8`. - - `auto_flush` (Integer): The number of queries after which the cache is flushed. Defaults to `20`. -7. `memory` Section: (Optional) - - `top_k` (Integer): The number of top-k results to return. Defaults to `10`. - - If you provide a cache section, the app will automatically configure and use a cache to store the results of the language model. This is useful if you want to speed up the response time and save inference cost of your app. - -If you have questions about the configuration above, please feel free to reach out to us using one of the following methods: - - \ No newline at end of file diff --git a/embedchain/docs/api-reference/app/add.mdx b/embedchain/docs/api-reference/app/add.mdx deleted file mode 100644 index 21b24de34..000000000 --- a/embedchain/docs/api-reference/app/add.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: '📊 add' ---- - -`add()` method is used to load the data sources from different data sources to a RAG pipeline. You can find the signature below: - -### Parameters - - - The data to embed, can be a URL, local file or raw content, depending on the data type.. You can find the full list of supported data sources [here](/components/data-sources/overview). - - - Type of data source. It can be automatically detected but user can force what data type to load as. - - - Any metadata that you want to store with the data source. Metadata is generally really useful for doing metadata filtering on top of semantic search to yield faster search and better results. - - - This parameter instructs Embedchain to retrieve all the context and information from the specified link, as well as from any reference links on the page. - - -## Usage - -### Load data from webpage - -```python Code example -from embedchain import App - -app = App() -app.add("https://www.forbes.com/profile/elon-musk") -# Inserting batches in chromadb: 100%|███████████████| 1/1 [00:00<00:00, 1.19it/s] -# Successfully saved https://www.forbes.com/profile/elon-musk (DataType.WEB_PAGE). New chunks count: 4 -``` - -### Load data from sitemap - -```python Code example -from embedchain import App - -app = App() -app.add("https://python.langchain.com/sitemap.xml", data_type="sitemap") -# Loading pages: 100%|█████████████| 1108/1108 [00:47<00:00, 23.17it/s] -# Inserting batches in chromadb: 100%|█████████| 111/111 [04:41<00:00, 2.54s/it] -# Successfully saved https://python.langchain.com/sitemap.xml (DataType.SITEMAP). New chunks count: 11024 -``` - -You can find complete list of supported data sources [here](/components/data-sources/overview). diff --git a/embedchain/docs/api-reference/app/chat.mdx b/embedchain/docs/api-reference/app/chat.mdx deleted file mode 100644 index f12b09793..000000000 --- a/embedchain/docs/api-reference/app/chat.mdx +++ /dev/null @@ -1,175 +0,0 @@ ---- -title: '💬 chat' ---- - -`chat()` method allows you to chat over your data sources using a user-friendly chat API. You can find the signature below: - -### Parameters - - - Question to ask - - - Configure different llm settings such as prompt, temprature, number_documents etc. - - - The purpose is to test the prompt structure without actually running LLM inference. Defaults to `False` - - - A dictionary of key-value pairs to filter the chunks from the vector database. Defaults to `None` - - - Session ID of the chat. This can be used to maintain chat history of different user sessions. Default value: `default` - - - Return citations along with the LLM answer. Defaults to `False` - - -### Returns - - - If `citations=False`, return a stringified answer to the question asked.
- If `citations=True`, returns a tuple with answer and citations respectively. -
- -## Usage - -### With citations - -If you want to get the answer to question and return both answer and citations, use the following code snippet: - -```python With Citations -from embedchain import App - -# Initialize app -app = App() - -# Add data source -app.add("https://www.forbes.com/profile/elon-musk") - -# Get relevant answer for your query -answer, sources = app.chat("What is the net worth of Elon?", citations=True) -print(answer) -# Answer: The net worth of Elon Musk is $221.9 billion. - -print(sources) -# [ -# ( -# 'Elon Musk PROFILEElon MuskCEO, Tesla$247.1B$2.3B (0.96%)Real Time Net Worthas of 12/7/23 ...', -# { -# 'url': 'https://www.forbes.com/profile/elon-musk', -# 'score': 0.89, -# ... -# } -# ), -# ( -# '74% of the company, which is now called X.Wealth HistoryHOVER TO REVEAL NET WORTH BY YEARForbes ...', -# { -# 'url': 'https://www.forbes.com/profile/elon-musk', -# 'score': 0.81, -# ... -# } -# ), -# ( -# 'founded in 2002, is worth nearly $150 billion after a $750 million tender offer in June 2023 ...', -# { -# 'url': 'https://www.forbes.com/profile/elon-musk', -# 'score': 0.73, -# ... -# } -# ) -# ] -``` - - -When `citations=True`, note that the returned `sources` are a list of tuples where each tuple has two elements (in the following order): -1. source chunk -2. dictionary with metadata about the source chunk - - `url`: url of the source - - `doc_id`: document id (used for book keeping purposes) - - `score`: score of the source chunk with respect to the question - - other metadata you might have added at the time of adding the source - - - -### Without citations - -If you just want to return answers and don't want to return citations, you can use the following example: - -```python Without Citations -from embedchain import App - -# Initialize app -app = App() - -# Add data source -app.add("https://www.forbes.com/profile/elon-musk") - -# Chat on your data using `.chat()` -answer = app.chat("What is the net worth of Elon?") -print(answer) -# Answer: The net worth of Elon Musk is $221.9 billion. -``` - -### With session id - -If you want to maintain chat sessions for different users, you can simply pass the `session_id` keyword argument. See the example below: - -```python With session id -from embedchain import App - -app = App() -app.add("https://www.forbes.com/profile/elon-musk") - -# Chat on your data using `.chat()` -app.chat("What is the net worth of Elon Musk?", session_id="user1") -# 'The net worth of Elon Musk is $250.8 billion.' -app.chat("What is the net worth of Bill Gates?", session_id="user2") -# "I don't know the current net worth of Bill Gates." -app.chat("What was my last question", session_id="user1") -# 'Your last question was "What is the net worth of Elon Musk?"' -``` - -### With custom context window - -If you want to customize the context window that you want to use during chat (default context window is 3 document chunks), you can do using the following code snippet: - -```python with custom chunks size -from embedchain import App -from embedchain.config import BaseLlmConfig - -app = App() -app.add("https://www.forbes.com/profile/elon-musk") - -query_config = BaseLlmConfig(number_documents=5) -app.chat("What is the net worth of Elon Musk?", config=query_config) -``` - -### With Mem0 to store chat history - -Mem0 is a cutting-edge long-term memory for LLMs to enable personalization for the GenAI stack. It enables LLMs to remember past interactions and provide more personalized responses. - -In order to use Mem0 to enable memory for personalization in your apps: -- Install the [`mem0`](https://docs.mem0.ai/) package using `pip install mem0ai`. -- Prepare config for `memory`, refer [Configurations](docs/api-reference/advanced/configuration.mdx). - -```python with mem0 -from embedchain import App - -config = { - "memory": { - "top_k": 5 - } -} - -app = App.from_config(config=config) -app.add("https://www.forbes.com/profile/elon-musk") - -app.chat("What is the net worth of Elon Musk?") -``` - -## How Mem0 works: -- Mem0 saves context derived from each user question into its memory. -- When a user poses a new question, Mem0 retrieves relevant previous memories. -- The `top_k` parameter in the memory configuration specifies the number of top memories to consider during retrieval. -- Mem0 generates the final response by integrating the user's question, context from the data source, and the relevant memories. diff --git a/embedchain/docs/api-reference/app/delete.mdx b/embedchain/docs/api-reference/app/delete.mdx deleted file mode 100644 index d1f2ceda4..000000000 --- a/embedchain/docs/api-reference/app/delete.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: 🗑 delete ---- - -## Delete Document - -`delete()` method allows you to delete a document previously added to the app. - -### Usage - -```python -from embedchain import App - -app = App() - -forbes_doc_id = app.add("https://www.forbes.com/profile/elon-musk") -wiki_doc_id = app.add("https://en.wikipedia.org/wiki/Elon_Musk") - -app.delete(forbes_doc_id) # deletes the forbes document -``` - - - If you do not have the document id, you can use `app.db.get()` method to get the document and extract the `hash` key from `metadatas` dictionary object, which serves as the document id. - - - -## Delete Chat Session History - -`delete_session_chat_history()` method allows you to delete all previous messages in a chat history. - -### Usage - -```python -from embedchain import App - -app = App() - -app.add("https://www.forbes.com/profile/elon-musk") - -app.chat("What is the net worth of Elon Musk?") - -app.delete_session_chat_history() -``` - - - `delete_session_chat_history(session_id="session_1")` method also accepts `session_id` optional param for deleting chat history of a specific session. - It assumes the default session if no `session_id` is provided. - \ No newline at end of file diff --git a/embedchain/docs/api-reference/app/deploy.mdx b/embedchain/docs/api-reference/app/deploy.mdx deleted file mode 100644 index 7cb8ff5e8..000000000 --- a/embedchain/docs/api-reference/app/deploy.mdx +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: 🚀 deploy ---- - -The `deploy()` method is currently available on an invitation-only basis. To request access, please submit your information via the provided [Google Form](https://forms.gle/vigN11h7b4Ywat668). We will review your request and respond promptly. diff --git a/embedchain/docs/api-reference/app/evaluate.mdx b/embedchain/docs/api-reference/app/evaluate.mdx deleted file mode 100644 index 64cb612ca..000000000 --- a/embedchain/docs/api-reference/app/evaluate.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: '📝 evaluate' ---- - -`evaluate()` method is used to evaluate the performance of a RAG app. You can find the signature below: - -### Parameters - - - A question or a list of questions to evaluate your app on. - - - The metrics to evaluate your app on. Defaults to all metrics: `["context_relevancy", "answer_relevancy", "groundedness"]` - - - Specify the number of threads to use for parallel processing. - - -### Returns - - - Returns the metrics you have chosen to evaluate your app on as a dictionary. - - -## Usage - -```python -from embedchain import App - -app = App() - -# add data source -app.add("https://www.forbes.com/profile/elon-musk") - -# run evaluation -app.evaluate("what is the net worth of Elon Musk?") -# {'answer_relevancy': 0.958019958036268, 'context_relevancy': 0.12903225806451613} - -# or -# app.evaluate(["what is the net worth of Elon Musk?", "which companies does Elon Musk own?"]) -``` diff --git a/embedchain/docs/api-reference/app/get.mdx b/embedchain/docs/api-reference/app/get.mdx deleted file mode 100644 index 252c78508..000000000 --- a/embedchain/docs/api-reference/app/get.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: 📄 get ---- - -## Get data sources - -`get_data_sources()` returns a list of all the data sources added in the app. - - -### Usage - -```python -from embedchain import App - -app = App() - -app.add("https://www.forbes.com/profile/elon-musk") -app.add("https://en.wikipedia.org/wiki/Elon_Musk") - -data_sources = app.get_data_sources() -# [ -# { -# 'data_type': 'web_page', -# 'data_value': 'https://en.wikipedia.org/wiki/Elon_Musk', -# 'metadata': 'null' -# }, -# { -# 'data_type': 'web_page', -# 'data_value': 'https://www.forbes.com/profile/elon-musk', -# 'metadata': 'null' -# } -# ] -``` \ No newline at end of file diff --git a/embedchain/docs/api-reference/app/overview.mdx b/embedchain/docs/api-reference/app/overview.mdx deleted file mode 100644 index 8c369cbf8..000000000 --- a/embedchain/docs/api-reference/app/overview.mdx +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: "App" ---- - -Create a RAG app object on Embedchain. This is the main entrypoint for a developer to interact with Embedchain APIs. An app configures the llm, vector database, embedding model, and retrieval strategy of your choice. - -### Attributes - - - App ID - - - Name of the app - - - Configuration of the app - - - Configured LLM for the RAG app - - - Configured vector database for the RAG app - - - Configured embedding model for the RAG app - - - Chunker configuration - - - Client object (used to deploy an app to Embedchain platform) - - - Logger object - - -## Usage - -You can create an app instance using the following methods: - -### Default setting - -```python Code Example -from embedchain import App -app = App() -``` - - -### Python Dict - -```python Code Example -from embedchain import App - -config_dict = { - 'llm': { - 'provider': 'gpt4all', - 'config': { - 'model': 'orca-mini-3b-gguf2-q4_0.gguf', - 'temperature': 0.5, - 'max_tokens': 1000, - 'top_p': 1, - 'stream': False - } - }, - 'embedder': { - 'provider': 'gpt4all' - } -} - -# load llm configuration from config dict -app = App.from_config(config=config_dict) -``` - -### YAML Config - - - -```python main.py -from embedchain import App - -# load llm configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: gpt4all - config: - model: 'orca-mini-3b-gguf2-q4_0.gguf' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -embedder: - provider: gpt4all -``` - - - -### JSON Config - - - -```python main.py -from embedchain import App - -# load llm configuration from config.json file -app = App.from_config(config_path="config.json") -``` - -```json config.json -{ - "llm": { - "provider": "gpt4all", - "config": { - "model": "orca-mini-3b-gguf2-q4_0.gguf", - "temperature": 0.5, - "max_tokens": 1000, - "top_p": 1, - "stream": false - } - }, - "embedder": { - "provider": "gpt4all" - } -} -``` - - diff --git a/embedchain/docs/api-reference/app/query.mdx b/embedchain/docs/api-reference/app/query.mdx deleted file mode 100644 index f1d94aa8f..000000000 --- a/embedchain/docs/api-reference/app/query.mdx +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: '❓ query' ---- - -`.query()` method empowers developers to ask questions and receive relevant answers through a user-friendly query API. Function signature is given below: - -### Parameters - - - Question to ask - - - Configure different llm settings such as prompt, temprature, number_documents etc. - - - The purpose is to test the prompt structure without actually running LLM inference. Defaults to `False` - - - A dictionary of key-value pairs to filter the chunks from the vector database. Defaults to `None` - - - Return citations along with the LLM answer. Defaults to `False` - - -### Returns - - - If `citations=False`, return a stringified answer to the question asked.
- If `citations=True`, returns a tuple with answer and citations respectively. -
- -## Usage - -### With citations - -If you want to get the answer to question and return both answer and citations, use the following code snippet: - -```python With Citations -from embedchain import App - -# Initialize app -app = App() - -# Add data source -app.add("https://www.forbes.com/profile/elon-musk") - -# Get relevant answer for your query -answer, sources = app.query("What is the net worth of Elon?", citations=True) -print(answer) -# Answer: The net worth of Elon Musk is $221.9 billion. - -print(sources) -# [ -# ( -# 'Elon Musk PROFILEElon MuskCEO, Tesla$247.1B$2.3B (0.96%)Real Time Net Worthas of 12/7/23 ...', -# { -# 'url': 'https://www.forbes.com/profile/elon-musk', -# 'score': 0.89, -# ... -# } -# ), -# ( -# '74% of the company, which is now called X.Wealth HistoryHOVER TO REVEAL NET WORTH BY YEARForbes ...', -# { -# 'url': 'https://www.forbes.com/profile/elon-musk', -# 'score': 0.81, -# ... -# } -# ), -# ( -# 'founded in 2002, is worth nearly $150 billion after a $750 million tender offer in June 2023 ...', -# { -# 'url': 'https://www.forbes.com/profile/elon-musk', -# 'score': 0.73, -# ... -# } -# ) -# ] -``` - - -When `citations=True`, note that the returned `sources` are a list of tuples where each tuple has two elements (in the following order): -1. source chunk -2. dictionary with metadata about the source chunk - - `url`: url of the source - - `doc_id`: document id (used for book keeping purposes) - - `score`: score of the source chunk with respect to the question - - other metadata you might have added at the time of adding the source - - -### Without citations - -If you just want to return answers and don't want to return citations, you can use the following example: - -```python Without Citations -from embedchain import App - -# Initialize app -app = App() - -# Add data source -app.add("https://www.forbes.com/profile/elon-musk") - -# Get relevant answer for your query -answer = app.query("What is the net worth of Elon?") -print(answer) -# Answer: The net worth of Elon Musk is $221.9 billion. -``` - diff --git a/embedchain/docs/api-reference/app/reset.mdx b/embedchain/docs/api-reference/app/reset.mdx deleted file mode 100644 index 07e136d86..000000000 --- a/embedchain/docs/api-reference/app/reset.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 🔄 reset ---- - -`reset()` method allows you to wipe the data from your RAG application and start from scratch. - -## Usage - -```python -from embedchain import App - -app = App() -app.add("https://www.forbes.com/profile/elon-musk") - -# Reset the app -app.reset() -``` \ No newline at end of file diff --git a/embedchain/docs/api-reference/app/search.mdx b/embedchain/docs/api-reference/app/search.mdx deleted file mode 100644 index db4eee1b2..000000000 --- a/embedchain/docs/api-reference/app/search.mdx +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: '🔍 search' ---- - -`.search()` enables you to uncover the most pertinent context by performing a semantic search across your data sources based on a given query. Refer to the function signature below: - -### Parameters - - - Question - - - Number of relevant documents to fetch. Defaults to `3` - - - Key value pair for metadata filtering. - - - Pass raw filter query based on your vector database. - Currently, `raw_filter` param is only supported for Pinecone vector database. - - -### Returns - - - Return list of dictionaries that contain the relevant chunk and their source information. - - -## Usage - -### Basic - -Refer to the following example on how to use the search api: - -```python Code example -from embedchain import App - -app = App() -app.add("https://www.forbes.com/profile/elon-musk") - -context = app.search("What is the net worth of Elon?", num_documents=2) -print(context) -``` - -### Advanced - -#### Metadata filtering using `where` params - -Here is an advanced example of `search()` API with metadata filtering on pinecone database: - -```python -import os - -from embedchain import App - -os.environ["PINECONE_API_KEY"] = "xxx" - -config = { - "vectordb": { - "provider": "pinecone", - "config": { - "metric": "dotproduct", - "vector_dimension": 1536, - "index_name": "ec-test", - "serverless_config": {"cloud": "aws", "region": "us-west-2"}, - }, - } -} - -app = App.from_config(config=config) - -app.add("https://www.forbes.com/profile/bill-gates", metadata={"type": "forbes", "person": "gates"}) -app.add("https://en.wikipedia.org/wiki/Bill_Gates", metadata={"type": "wiki", "person": "gates"}) - -results = app.search("What is the net worth of Bill Gates?", where={"person": "gates"}) -print("Num of search results: ", len(results)) -``` - -#### Metadata filtering using `raw_filter` params - -Following is an example of metadata filtering by passing the raw filter query that pinecone vector database follows: - -```python -import os - -from embedchain import App - -os.environ["PINECONE_API_KEY"] = "xxx" - -config = { - "vectordb": { - "provider": "pinecone", - "config": { - "metric": "dotproduct", - "vector_dimension": 1536, - "index_name": "ec-test", - "serverless_config": {"cloud": "aws", "region": "us-west-2"}, - }, - } -} - -app = App.from_config(config=config) - -app.add("https://www.forbes.com/profile/bill-gates", metadata={"year": 2022, "person": "gates"}) -app.add("https://en.wikipedia.org/wiki/Bill_Gates", metadata={"year": 2024, "person": "gates"}) - -print("Filter with person: gates and year > 2023") -raw_filter = {"$and": [{"person": "gates"}, {"year": {"$gt": 2023}}]} -results = app.search("What is the net worth of Bill Gates?", raw_filter=raw_filter) -print("Num of search results: ", len(results)) -``` diff --git a/embedchain/docs/api-reference/overview.mdx b/embedchain/docs/api-reference/overview.mdx deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/docs/api-reference/store/ai-assistants.mdx b/embedchain/docs/api-reference/store/ai-assistants.mdx deleted file mode 100644 index 09c6122a4..000000000 --- a/embedchain/docs/api-reference/store/ai-assistants.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: 'AI Assistant' ---- - -The `AIAssistant` class, an alternative to the OpenAI Assistant API, is designed for those who prefer using large language models (LLMs) other than those provided by OpenAI. It facilitates the creation of AI Assistants with several key benefits: - -- **Visibility into Citations**: It offers transparent access to the sources and citations used by the AI, enhancing the understanding and trustworthiness of its responses. - -- **Debugging Capabilities**: Users have the ability to delve into and debug the AI's processes, allowing for a deeper understanding and fine-tuning of its performance. - -- **Customizable Prompts**: The class provides the flexibility to modify and tailor prompts according to specific needs, enabling more precise and relevant interactions. - -- **Chain of Thought Integration**: It supports the incorporation of a 'chain of thought' approach, which helps in breaking down complex queries into simpler, sequential steps, thereby improving the clarity and accuracy of responses. - -It is ideal for those who value customization, transparency, and detailed control over their AI Assistant's functionalities. - -### Arguments - - - Name for your AI assistant - - - - How the Assistant and model should behave or respond - - - - Load existing AI Assistant. If you pass this, you don't have to pass other arguments. - - - - Existing thread id if exists - - - - Embedchain pipeline config yaml path to use. This will define the configuration of the AI Assistant (such as configuring the LLM, vector database, and embedding model) - - - - Add data sources to your assistant. You can add in the following format: `[{"source": "https://example.com", "data_type": "web_page"}]` - - - - Anonymous telemetry (doesn't collect any user information or user's files). Used to improve the Embedchain package utilization. Default is `True`. - - - -## Usage - -For detailed guidance on creating your own AI Assistant, click the link below. It provides step-by-step instructions to help you through the process: - - - Learn how to build a customized AI Assistant using the `AIAssistant` class. - diff --git a/embedchain/docs/api-reference/store/openai-assistant.mdx b/embedchain/docs/api-reference/store/openai-assistant.mdx deleted file mode 100644 index 1ab21aa1f..000000000 --- a/embedchain/docs/api-reference/store/openai-assistant.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: 'OpenAI Assistant' ---- - -### Arguments - - - Name for your AI assistant - - - - how the Assistant and model should behave or respond - - - - Load existing OpenAI Assistant. If you pass this, you don't have to pass other arguments. - - - - Existing OpenAI thread id if exists - - - - OpenAI model to use - - - - OpenAI tools to use. Default set to `[{"type": "retrieval"}]` - - - - Add data sources to your assistant. You can add in the following format: `[{"source": "https://example.com", "data_type": "web_page"}]` - - - - Anonymous telemetry (doesn't collect any user information or user's files). Used to improve the Embedchain package utilization. Default is `True`. - - -## Usage - -For detailed guidance on creating your own OpenAI Assistant, click the link below. It provides step-by-step instructions to help you through the process: - - - Learn how to build an OpenAI Assistant using the `OpenAIAssistant` class. - diff --git a/embedchain/docs/community/connect-with-us.mdx b/embedchain/docs/community/connect-with-us.mdx deleted file mode 100644 index e08dfd1c7..000000000 --- a/embedchain/docs/community/connect-with-us.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: 🤝 Connect with Us ---- - -We believe in building a vibrant and supportive community around embedchain. There are various channels through which you can connect with us, stay updated, and contribute to the ongoing discussions: - - - - Follow us on Twitter - - - Join our slack community - - - Join our discord community - - - Connect with us on LinkedIn - - - Schedule a call with Embedchain founder - - - Subscribe to our newsletter - - - -We look forward to connecting with you and seeing how we can create amazing things together! diff --git a/embedchain/docs/components/data-sources/audio.mdx b/embedchain/docs/components/data-sources/audio.mdx deleted file mode 100644 index 5f2772a71..000000000 --- a/embedchain/docs/components/data-sources/audio.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: "🎤 Audio" ---- - - -To use an audio as data source, just add `data_type` as `audio` and pass in the path of the audio (local or hosted). - -We use [Deepgram](https://developers.deepgram.com/docs/introduction) to transcribe the audiot to text, and then use the generated text as the data source. - -You would require an Deepgram API key which is available [here](https://console.deepgram.com/signup?jump=keys) to use this feature. - -### Without customization - -```python -import os -from embedchain import App - -os.environ["DEEPGRAM_API_KEY"] = "153xxx" - -app = App() -app.add("introduction.wav", data_type="audio") -response = app.query("What is my name and how old am I?") -print(response) -# Answer: Your name is Dave and you are 21 years old. -``` diff --git a/embedchain/docs/components/data-sources/beehiiv.mdx b/embedchain/docs/components/data-sources/beehiiv.mdx deleted file mode 100644 index 5a94cf1fe..000000000 --- a/embedchain/docs/components/data-sources/beehiiv.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "🐝 Beehiiv" ---- - -To add any Beehiiv data sources to your app, just add the base url as the source and set the data_type to `beehiiv`. - -```python -from embedchain import App - -app = App() - -# source: just add the base url and set the data_type to 'beehiiv' -app.add('https://aibreakfast.beehiiv.com', data_type='beehiiv') -app.query("How much is OpenAI paying developers?") -# Answer: OpenAI is aggressively recruiting Google's top AI researchers with offers ranging between $5 to $10 million annually, primarily in stock options. -``` diff --git a/embedchain/docs/components/data-sources/csv.mdx b/embedchain/docs/components/data-sources/csv.mdx deleted file mode 100644 index 07663a3b1..000000000 --- a/embedchain/docs/components/data-sources/csv.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: '📊 CSV' ---- - -You can load any csv file from your local file system or through a URL. Headers are included for each line, so if you have an `age` column, `18` will be added as `age: 18`. - -## Usage - -### Load from a local file - -```python -from embedchain import App -app = App() -app.add('/path/to/file.csv', data_type='csv') -``` - -### Load from URL - -```python -from embedchain import App -app = App() -app.add('https://people.sc.fsu.edu/~jburkardt/data/csv/airtravel.csv', data_type="csv") -``` - - -There is a size limit allowed for csv file beyond which it can throw error. This limit is set by the LLMs. Please consider chunking large csv files into smaller csv files. - - diff --git a/embedchain/docs/components/data-sources/custom.mdx b/embedchain/docs/components/data-sources/custom.mdx deleted file mode 100644 index 40a8c75e1..000000000 --- a/embedchain/docs/components/data-sources/custom.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: '⚙️ Custom' ---- - -When we say "custom", we mean that you can customize the loader and chunker to your needs. This is done by passing a custom loader and chunker to the `add` method. - -```python -from embedchain import App -import your_loader -from my_module import CustomLoader -from my_module import CustomChunker - -app = App() -loader = CustomLoader() -chunker = CustomChunker() - -app.add("source", data_type="custom", loader=loader, chunker=chunker) -``` - - - The custom loader and chunker must be a class that inherits from the [`BaseLoader`](https://github.com/embedchain/embedchain/blob/main/embedchain/loaders/base_loader.py) and [`BaseChunker`](https://github.com/embedchain/embedchain/blob/main/embedchain/chunkers/base_chunker.py) classes respectively. - - - - If the `data_type` is not a valid data type, the `add` method will fallback to the `custom` data type and expect a custom loader and chunker to be passed by the user. - - -Example: - -```python -from embedchain import App -from embedchain.loaders.github import GithubLoader - -app = App() - -loader = GithubLoader(config={"token": "ghp_xxx"}) - -app.add("repo:embedchain/embedchain type:repo", data_type="github", loader=loader) - -app.query("What is Embedchain?") -# Answer: Embedchain is a Data Platform for Large Language Models (LLMs). It allows users to seamlessly load, index, retrieve, and sync unstructured data in order to build dynamic, LLM-powered applications. There is also a JavaScript implementation called embedchain-js available on GitHub. -``` diff --git a/embedchain/docs/components/data-sources/data-type-handling.mdx b/embedchain/docs/components/data-sources/data-type-handling.mdx deleted file mode 100644 index d939537af..000000000 --- a/embedchain/docs/components/data-sources/data-type-handling.mdx +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: 'Data type handling' ---- - -## Automatic data type detection - -The add method automatically tries to detect the data_type, based on your input for the source argument. So `app.add('https://www.youtube.com/watch?v=dQw4w9WgXcQ')` is enough to embed a YouTube video. - -This detection is implemented for all formats. It is based on factors such as whether it's a URL, a local file, the source data type, etc. - -### Debugging automatic detection - -Set `log_level: DEBUG` in the config yaml to debug if the data type detection is done right or not. Otherwise, you will not know when, for instance, an invalid filepath is interpreted as raw text instead. - -### Forcing a data type - -To omit any issues with the data type detection, you can **force** a data_type by adding it as a `add` method argument. -The examples below show you the keyword to force the respective `data_type`. - -Forcing can also be used for edge cases, such as interpreting a sitemap as a web_page, for reading its raw text instead of following links. - -## Remote data types - - -**Use local files in remote data types** - -Some data_types are meant for remote content and only work with URLs. -You can pass local files by formatting the path using the `file:` [URI scheme](https://en.wikipedia.org/wiki/File_URI_scheme), e.g. `file:///info.pdf`. - - -## Reusing a vector database - -Default behavior is to create a persistent vector db in the directory **./db**. You can split your application into two Python scripts: one to create a local vector db and the other to reuse this local persistent vector db. This is useful when you want to index hundreds of documents and separately implement a chat interface. - -Create a local index: - -```python -from embedchain import App - -config = { - "app": { - "config": { - "id": "app-1" - } - } -} -naval_chat_bot = App.from_config(config=config) -naval_chat_bot.add("https://www.youtube.com/watch?v=3qHkcs3kG44") -naval_chat_bot.add("https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf") -``` - -You can reuse the local index with the same code, but without adding new documents: - -```python -from embedchain import App - -config = { - "app": { - "config": { - "id": "app-1" - } - } -} -naval_chat_bot = App.from_config(config=config) -print(naval_chat_bot.query("What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?")) -``` - -## Resetting an app and vector database - -You can reset the app by simply calling the `reset` method. This will delete the vector database and all other app related files. - -```python -from embedchain import App - -app = App()config = { - "app": { - "config": { - "id": "app-1" - } - } -} -naval_chat_bot = App.from_config(config=config) -app.add("https://www.youtube.com/watch?v=3qHkcs3kG44") -app.reset() -``` diff --git a/embedchain/docs/components/data-sources/directory.mdx b/embedchain/docs/components/data-sources/directory.mdx deleted file mode 100644 index 33c1e9b73..000000000 --- a/embedchain/docs/components/data-sources/directory.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: '📁 Directory/Folder' ---- - -To use an entire directory as data source, just add `data_type` as `directory` and pass in the path of the local directory. - -### Without customization - -```python -import os -from embedchain import App - -os.environ["OPENAI_API_KEY"] = "sk-xxx" - -app = App() -app.add("./elon-musk", data_type="directory") -response = app.query("list all files") -print(response) -# Answer: Files are elon-musk-1.txt, elon-musk-2.pdf. -``` - -### Customization - -```python -import os -from embedchain import App -from embedchain.loaders.directory_loader import DirectoryLoader - -os.environ["OPENAI_API_KEY"] = "sk-xxx" -lconfig = { - "recursive": True, - "extensions": [".txt"] -} -loader = DirectoryLoader(config=lconfig) -app = App() -app.add("./elon-musk", loader=loader) -response = app.query("what are all the files related to?") -print(response) - -# Answer: The files are related to Elon Musk. -``` diff --git a/embedchain/docs/components/data-sources/discord.mdx b/embedchain/docs/components/data-sources/discord.mdx deleted file mode 100644 index 2c8780210..000000000 --- a/embedchain/docs/components/data-sources/discord.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "💬 Discord" ---- - -To add any Discord channel messages to your app, just add the `channel_id` as the source and set the `data_type` to `discord`. - - - This loader requires a Discord bot token with read messages access. - To obtain the token, follow the instructions provided in this tutorial: - How to Get a Discord Bot Token?. - - -```python -import os -from embedchain import App - -# add your discord "BOT" token -os.environ["DISCORD_TOKEN"] = "xxx" - -app = App() - -app.add("1177296711023075338", data_type="discord") - -response = app.query("What is Joe saying about Elon Musk?") - -print(response) -# Answer: Joe is saying "Elon Musk is a genius". -``` diff --git a/embedchain/docs/components/data-sources/discourse.mdx b/embedchain/docs/components/data-sources/discourse.mdx deleted file mode 100644 index 4ba0a36ce..000000000 --- a/embedchain/docs/components/data-sources/discourse.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: '🗨️ Discourse' ---- - -You can now easily load data from your community built with [Discourse](https://discourse.org/). - -## Example - -1. Setup the Discourse Loader with your community url. -```Python -from embedchain.loaders.discourse import DiscourseLoader - -dicourse_loader = DiscourseLoader(config={"domain": "https://community.openai.com"}) -``` - -2. Once you setup the loader, you can create an app and load data using the above discourse loader -```Python -import os -from embedchain.pipeline import Pipeline as App - -os.environ["OPENAI_API_KEY"] = "sk-xxx" - -app = App() - -app.add("openai after:2023-10-1", data_type="discourse", loader=dicourse_loader) - -question = "Where can I find the OpenAI API status page?" -app.query(question) -# Answer: You can find the OpenAI API status page at https:/status.openai.com/. -``` - -NOTE: The `add` function of the app will accept any executable search query to load data. Refer [Discourse API Docs](https://docs.discourse.org/#tag/Search) to learn more about search queries. - -3. We automatically create a chunker to chunk your discourse data, however if you wish to provide your own chunker class. Here is how you can do that: -```Python - -from embedchain.chunkers.discourse import DiscourseChunker -from embedchain.config.add_config import ChunkerConfig - -discourse_chunker_config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) -discourse_chunker = DiscourseChunker(config=discourse_chunker_config) - -app.add("openai", data_type='discourse', loader=dicourse_loader, chunker=discourse_chunker) -``` \ No newline at end of file diff --git a/embedchain/docs/components/data-sources/docs-site.mdx b/embedchain/docs/components/data-sources/docs-site.mdx deleted file mode 100644 index 342bbdc85..000000000 --- a/embedchain/docs/components/data-sources/docs-site.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: '📚 Code Docs website' ---- - -To add any code documentation website as a loader, use the data_type as `docs_site`. Eg: - -```python -from embedchain import App - -app = App() -app.add("https://docs.embedchain.ai/", data_type="docs_site") -app.query("What is Embedchain?") -# Answer: Embedchain is a platform that utilizes various components, including paid/proprietary ones, to provide what is believed to be the best configuration available. It uses LLM (Language Model) providers such as OpenAI, Anthpropic, Vertex_AI, GPT4ALL, Azure_OpenAI, LLAMA2, JINA, Ollama, Together and COHERE. Embedchain allows users to import and utilize these LLM providers for their applications.' -``` diff --git a/embedchain/docs/components/data-sources/docx.mdx b/embedchain/docs/components/data-sources/docx.mdx deleted file mode 100644 index cc459621f..000000000 --- a/embedchain/docs/components/data-sources/docx.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: '📄 Docx file' ---- - -### Docx file - -To add any doc/docx file, use the data_type as `docx`. `docx` allows remote urls and conventional file paths. Eg: - -```python -from embedchain import App - -app = App() -app.add('https://example.com/content/intro.docx', data_type="docx") -# Or add file using the local file path on your system -# app.add('content/intro.docx', data_type="docx") - -app.query("Summarize the docx data?") -``` diff --git a/embedchain/docs/components/data-sources/dropbox.mdx b/embedchain/docs/components/data-sources/dropbox.mdx deleted file mode 100644 index bb2800bf8..000000000 --- a/embedchain/docs/components/data-sources/dropbox.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: '💾 Dropbox' ---- - -To load folders or files from your Dropbox account, configure the `data_type` parameter as `dropbox` and specify the path to the desired file or folder, starting from the root directory of your Dropbox account. - -For Dropbox access, an **access token** is required. Obtain this token by visiting [Dropbox Developer Apps](https://www.dropbox.com/developers/apps). There, create a new app and generate an access token for it. - -Ensure your app has the following settings activated: - -- In the Permissions section, enable `files.content.read` and `files.metadata.read`. - -## Usage - -Install the `dropbox` pypi package: - -```bash -pip install dropbox -``` - -Following is an example of how to use the dropbox loader: - -```python -import os -from embedchain import App - -os.environ["DROPBOX_ACCESS_TOKEN"] = "sl.xxx" -os.environ["OPENAI_API_KEY"] = "sk-xxx" - -app = App() - -# any path from the root of your dropbox account, you can leave it "" for the root folder -app.add("/test", data_type="dropbox") - -print(app.query("Which two celebrities are mentioned here?")) -# The two celebrities mentioned in the given context are Elon Musk and Jeff Bezos. -``` diff --git a/embedchain/docs/components/data-sources/excel-file.mdx b/embedchain/docs/components/data-sources/excel-file.mdx deleted file mode 100644 index af8a2cd62..000000000 --- a/embedchain/docs/components/data-sources/excel-file.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: '📄 Excel file' ---- - -### Excel file - -To add any xlsx/xls file, use the data_type as `excel_file`. `excel_file` allows remote urls and conventional file paths. Eg: - -```python -from embedchain import App - -app = App() -app.add('https://example.com/content/intro.xlsx', data_type="excel_file") -# Or add file using the local file path on your system -# app.add('content/intro.xls', data_type="excel_file") - -app.query("Give brief information about data.") -``` diff --git a/embedchain/docs/components/data-sources/github.mdx b/embedchain/docs/components/data-sources/github.mdx deleted file mode 100644 index 14791aca4..000000000 --- a/embedchain/docs/components/data-sources/github.mdx +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: 📝 Github ---- - -1. Setup the Github loader by configuring the Github account with username and personal access token (PAT). Check out [this](https://docs.github.com/en/enterprise-server@3.6/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token) link to learn how to create a PAT. -```Python -from embedchain.loaders.github import GithubLoader - -loader = GithubLoader( - config={ - "token":"ghp_xxxx" - } - ) -``` - -2. Once you setup the loader, you can create an app and load data using the above Github loader -```Python -import os -from embedchain.pipeline import Pipeline as App - -os.environ["OPENAI_API_KEY"] = "sk-xxxx" - -app = App() - -app.add("repo:embedchain/embedchain type:repo", data_type="github", loader=loader) - -response = app.query("What is Embedchain?") -# Answer: Embedchain is a Data Platform for Large Language Models (LLMs). It allows users to seamlessly load, index, retrieve, and sync unstructured data in order to build dynamic, LLM-powered applications. There is also a JavaScript implementation called embedchain-js available on GitHub. -``` -The `add` function of the app will accept any valid github query with qualifiers. It only supports loading github code, repository, issues and pull-requests. - -You must provide qualifiers `type:` and `repo:` in the query. The `type:` qualifier can be a combination of `code`, `repo`, `pr`, `issue`, `branch`, `file`. The `repo:` qualifier must be a valid github repository name. - - - - - `repo:embedchain/embedchain type:repo` - to load the repository - - `repo:embedchain/embedchain type:branch name:feature_test` - to load the branch of the repository - - `repo:embedchain/embedchain type:file path:README.md` - to load the specific file of the repository - - `repo:embedchain/embedchain type:issue,pr` - to load the issues and pull-requests of the repository - - `repo:embedchain/embedchain type:issue state:closed` - to load the closed issues of the repository - - -3. We automatically create a chunker to chunk your GitHub data, however if you wish to provide your own chunker class. Here is how you can do that: -```Python -from embedchain.chunkers.common_chunker import CommonChunker -from embedchain.config.add_config import ChunkerConfig - -github_chunker_config = ChunkerConfig(chunk_size=2000, chunk_overlap=0, length_function=len) -github_chunker = CommonChunker(config=github_chunker_config) - -app.add(load_query, data_type="github", loader=loader, chunker=github_chunker) -``` diff --git a/embedchain/docs/components/data-sources/gmail.mdx b/embedchain/docs/components/data-sources/gmail.mdx deleted file mode 100644 index aaaf002ed..000000000 --- a/embedchain/docs/components/data-sources/gmail.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: '📬 Gmail' ---- - -To use GmailLoader you must install the extra dependencies with `pip install --upgrade embedchain[gmail]`. - -The `source` must be a valid Gmail search query, you can refer `https://support.google.com/mail/answer/7190?hl=en` to build a query. - -To load Gmail messages, you MUST use the data_type as `gmail`. Otherwise the source will be detected as simple `text`. - -To use this you need to save `credentials.json` in the directory from where you will run the loader. Follow these steps to get the credentials - -1. Go to the [Google Cloud Console](https://console.cloud.google.com/apis/credentials). -2. Create a project if you don't have one already. -3. Create an `OAuth Consent Screen` in the project. You may need to select the `external` option. -4. Make sure the consent screen is published. -5. Enable the [Gmail API](https://console.cloud.google.com/apis/api/gmail.googleapis.com) -6. Create credentials from the `Credentials` tab. -7. Select the type `OAuth Client ID`. -8. Choose the application type `Web application`. As a name you can choose `embedchain` or any other name as per your use case. -9. Add an authorized redirect URI for `http://localhost:8080/`. -10. You can leave everything else at default, finish the creation. -11. When you are done, a modal opens where you can download the details in `json` format. -12. Put the `.json` file in your current directory and rename it to `credentials.json` - -```python -from embedchain import App - -app = App() - -gmail_filter = "to: me label:inbox" -app.add(gmail_filter, data_type="gmail") -app.query("Summarize my email conversations") -``` \ No newline at end of file diff --git a/embedchain/docs/components/data-sources/google-drive.mdx b/embedchain/docs/components/data-sources/google-drive.mdx deleted file mode 100644 index 5dcf4e45f..000000000 --- a/embedchain/docs/components/data-sources/google-drive.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: 'Google Drive' ---- - -To use GoogleDriveLoader you must install the extra dependencies with `pip install --upgrade embedchain[googledrive]`. - -The data_type must be `google_drive`. Otherwise, it will be considered a regular web page. - -Google Drive requires the setup of credentials. This can be done by following the steps below: - -1. Go to the [Google Cloud Console](https://console.cloud.google.com/apis/credentials). -2. Create a project if you don't have one already. -3. Enable the [Google Drive API](https://console.cloud.google.com/flows/enableapi?apiid=drive.googleapis.com) -4. [Authorize credentials for desktop app](https://developers.google.com/drive/api/quickstart/python#authorize_credentials_for_a_desktop_application) -5. When done, you will be able to download the credentials in `json` format. Rename the downloaded file to `credentials.json` and save it in `~/.credentials/credentials.json` -6. Set the environment variable `GOOGLE_APPLICATION_CREDENTIALS=~/.credentials/credentials.json` - -The first time you use the loader, you will be prompted to enter your Google account credentials. - - -```python -from embedchain import App - -app = App() - -url = "https://drive.google.com/drive/u/0/folders/xxx-xxx" -app.add(url, data_type="google_drive") -``` diff --git a/embedchain/docs/components/data-sources/image.mdx b/embedchain/docs/components/data-sources/image.mdx deleted file mode 100644 index b79043660..000000000 --- a/embedchain/docs/components/data-sources/image.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: "🖼️ Image" ---- - - -To use an image as data source, just add `data_type` as `image` and pass in the path of the image (local or hosted). - -We use [GPT4 Vision](https://platform.openai.com/docs/guides/vision) to generate meaning of the image using a custom prompt, and then use the generated text as the data source. - -You would require an OpenAI API key with access to `gpt-4-vision-preview` model to use this feature. - -### Without customization - -```python -import os -from embedchain import App - -os.environ["OPENAI_API_KEY"] = "sk-xxx" - -app = App() -app.add("./Elon-Musk.webp", data_type="image") -response = app.query("Describe the man in the image.") -print(response) -# Answer: The man in the image is dressed in formal attire, wearing a dark suit jacket and a white collared shirt. He has short hair and is standing. He appears to be gazing off to the side with a reflective expression. The background is dark with faint, warm-toned vertical lines, possibly from a lit environment behind the individual or reflections. The overall atmosphere is somewhat moody and introspective. -``` - -### Customization - -```python -import os -from embedchain import App -from embedchain.loaders.image import ImageLoader - -image_loader = ImageLoader( - max_tokens=100, - api_key="sk-xxx", - prompt="Is the person looking wealthy? Structure your thoughts around what you see in the image.", -) - -app = App() -app.add("./Elon-Musk.webp", data_type="image", loader=image_loader) -response = app.query("Describe the man in the image.") -print(response) -# Answer: The man in the image appears to be well-dressed in a suit and shirt, suggesting that he may be in a professional or formal setting. His composed demeanor and confident posture further indicate a sense of self-assurance. Based on these visual cues, one could infer that the man may have a certain level of economic or social status, possibly indicating wealth or professional success. -``` diff --git a/embedchain/docs/components/data-sources/json.mdx b/embedchain/docs/components/data-sources/json.mdx deleted file mode 100644 index 4d38a0a55..000000000 --- a/embedchain/docs/components/data-sources/json.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: '📃 JSON' ---- - -To add any json file, use the data_type as `json`. Headers are included for each line, so for example if you have a json like `{"age": 18}`, then it will be added as `age: 18`. - -Here are the supported sources for loading `json`: - -``` -1. URL - valid url to json file that ends with ".json" extension. -2. Local file - valid url to local json file that ends with ".json" extension. -3. String - valid json string (e.g. - app.add('{"foo": "bar"}')) -``` - - -If you would like to add other data structures (e.g. list, dict etc.), convert it to a valid json first using `json.dumps()` function. - - -## Example - - - -```python python -from embedchain import App - -app = App() - -# Add json file -app.add("temp.json") - -app.query("What is the net worth of Elon Musk as of October 2023?") -# As of October 2023, Elon Musk's net worth is $255.2 billion. -``` - - -```json temp.json -{ - "question": "What is your net worth, Elon Musk?", - "answer": "As of October 2023, Elon Musk's net worth is $255.2 billion, making him one of the wealthiest individuals in the world." -} -``` - - - diff --git a/embedchain/docs/components/data-sources/mdx.mdx b/embedchain/docs/components/data-sources/mdx.mdx deleted file mode 100644 index c59569e50..000000000 --- a/embedchain/docs/components/data-sources/mdx.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: '📝 Mdx file' ---- - -To add any `.mdx` file to your app, use the data_type (first argument to `.add()` method) as `mdx`. Note that this supports support mdx file present on machine, so this should be a file path. Eg: - -```python -from embedchain import App - -app = App() -app.add('path/to/file.mdx', data_type='mdx') - -app.query("What are the docs about?") -``` diff --git a/embedchain/docs/components/data-sources/mysql.mdx b/embedchain/docs/components/data-sources/mysql.mdx deleted file mode 100644 index 2a5cb7a01..000000000 --- a/embedchain/docs/components/data-sources/mysql.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: '🐬 MySQL' ---- - -1. Setup the MySQL loader by configuring the SQL db. -```Python -from embedchain.loaders.mysql import MySQLLoader - -config = { - "host": "host", - "port": "port", - "database": "database", - "user": "username", - "password": "password", -} - -mysql_loader = MySQLLoader(config=config) -``` - -For more details on how to setup with valid config, check MySQL [documentation](https://dev.mysql.com/doc/connector-python/en/connector-python-connectargs.html). - -2. Once you setup the loader, you can create an app and load data using the above MySQL loader -```Python -from embedchain.pipeline import Pipeline as App - -app = App() - -app.add("SELECT * FROM table_name;", data_type='mysql', loader=mysql_loader) -# Adds `(1, 'What is your net worth, Elon Musk?', "As of October 2023, Elon Musk's net worth is $255.2 billion.")` - -response = app.query(question) -# Answer: As of October 2023, Elon Musk's net worth is $255.2 billion. -``` - -NOTE: The `add` function of the app will accept any executable query to load data. DO NOT pass the `CREATE`, `INSERT` queries in `add` function. - -3. We automatically create a chunker to chunk your SQL data, however if you wish to provide your own chunker class. Here is how you can do that: -```Python - -from embedchain.chunkers.mysql import MySQLChunker -from embedchain.config.add_config import ChunkerConfig - -mysql_chunker_config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) -mysql_chunker = MySQLChunker(config=mysql_chunker_config) - -app.add("SELECT * FROM table_name;", data_type='mysql', loader=mysql_loader, chunker=mysql_chunker) -``` diff --git a/embedchain/docs/components/data-sources/notion.mdx b/embedchain/docs/components/data-sources/notion.mdx deleted file mode 100644 index d6c616df8..000000000 --- a/embedchain/docs/components/data-sources/notion.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: '📓 Notion' ---- - -To use notion you must install the extra dependencies with `pip install --upgrade embedchain[community]`. - -To load a notion page, use the data_type as `notion`. Since it is hard to automatically detect, it is advised to specify the `data_type` when adding a notion document. -The next argument must **end** with the `notion page id`. The id is a 32-character string. Eg: - -```python -from embedchain import App - -app = App() - -app.add("cfbc134ca6464fc980d0391613959196", data_type="notion") -app.add("my-page-cfbc134ca6464fc980d0391613959196", data_type="notion") -app.add("https://www.notion.so/my-page-cfbc134ca6464fc980d0391613959196", data_type="notion") - -app.query("Summarize the notion doc") -``` diff --git a/embedchain/docs/components/data-sources/openapi.mdx b/embedchain/docs/components/data-sources/openapi.mdx deleted file mode 100644 index 84bc966b2..000000000 --- a/embedchain/docs/components/data-sources/openapi.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: 🙌 OpenAPI ---- - -To add any OpenAPI spec yaml file (currently the json file will be detected as JSON data type), use the data_type as 'openapi'. 'openapi' allows remote urls and conventional file paths. - -```python -from embedchain import App - -app = App() - -app.add("https://github.com/openai/openai-openapi/blob/master/openapi.yaml", data_type="openapi") -# Or add using the local file path -# app.add("configs/openai_openapi.yaml", data_type="openapi") - -app.query("What can OpenAI API endpoint do? Can you list the things it can learn from?") -# Answer: The OpenAI API endpoint allows users to interact with OpenAI's models and perform various tasks such as generating text, answering questions, summarizing documents, translating languages, and more. The specific capabilities and tasks that the API can learn from may vary depending on the models and features provided by OpenAI. For more detailed information, it is recommended to refer to the OpenAI API documentation at https://platform.openai.com/docs/api-reference. -``` - - -The yaml file added to the App must have the required OpenAPI fields otherwise the adding OpenAPI spec will fail. Please refer to [OpenAPI Spec Doc](https://spec.openapis.org/oas/v3.1.0) - \ No newline at end of file diff --git a/embedchain/docs/components/data-sources/overview.mdx b/embedchain/docs/components/data-sources/overview.mdx deleted file mode 100644 index 66f5948a3..000000000 --- a/embedchain/docs/components/data-sources/overview.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Overview ---- - -Embedchain comes with built-in support for various data sources. We handle the complexity of loading unstructured data from these data sources, allowing you to easily customize your app through a user-friendly interface. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - diff --git a/embedchain/docs/components/data-sources/pdf-file.mdx b/embedchain/docs/components/data-sources/pdf-file.mdx deleted file mode 100644 index 9cc45910a..000000000 --- a/embedchain/docs/components/data-sources/pdf-file.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: '📰 PDF' ---- - -You can load any pdf file from your local file system or through a URL. - -## Usage - -### Load from a local file - -```python -from embedchain import App -app = App() -app.add('/path/to/file.pdf', data_type='pdf_file') -``` - -### Load from URL - -```python -from embedchain import App -app = App() -app.add('https://arxiv.org/pdf/1706.03762.pdf', data_type='pdf_file') -app.query("What is the paper 'attention is all you need' about?", citations=True) -# Answer: The paper "Attention Is All You Need" proposes a new network architecture called the Transformer, which is based solely on attention mechanisms. It suggests that complex recurrent or convolutional neural networks can be replaced with a simpler architecture that connects the encoder and decoder through attention. The paper discusses how this approach can improve sequence transduction models, such as neural machine translation. -# Contexts: -# [ -# ( -# 'Provided proper attribution is ...', -# { -# 'page': 0, -# 'url': 'https://arxiv.org/pdf/1706.03762.pdf', -# 'score': 0.3676220203221626, -# ... -# } -# ), -# ] -``` - -We also store the page number under the key `page` with each chunk that helps understand where the answer is coming from. You can fetch the `page` key while during retrieval (refer to the example given above). - - -Note that we do not support password protected pdf files. - diff --git a/embedchain/docs/components/data-sources/postgres.mdx b/embedchain/docs/components/data-sources/postgres.mdx deleted file mode 100644 index 9cb5d0e6e..000000000 --- a/embedchain/docs/components/data-sources/postgres.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: '🐘 Postgres' ---- - -1. Setup the Postgres loader by configuring the postgres db. -```Python -from embedchain.loaders.postgres import PostgresLoader - -config = { - "host": "host_address", - "port": "port_number", - "dbname": "database_name", - "user": "username", - "password": "password", -} - -""" -config = { - "url": "your_postgres_url" -} -""" - -postgres_loader = PostgresLoader(config=config) - -``` - -You can either setup the loader by passing the postgresql url or by providing the config data. -For more details on how to setup with valid url and config, check postgres [documentation](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING:~:text=34.1.1.%C2%A0Connection%20Strings-,%23,-Several%20libpq%20functions). - -NOTE: if you provide the `url` field in config, all other fields will be ignored. - -2. Once you setup the loader, you can create an app and load data using the above postgres loader -```Python -import os -from embedchain.pipeline import Pipeline as App - -os.environ["OPENAI_API_KEY"] = "sk-xxx" - -app = App() - -question = "What is Elon Musk's networth?" -response = app.query(question) -# Answer: As of September 2021, Elon Musk's net worth is estimated to be around $250 billion, making him one of the wealthiest individuals in the world. However, please note that net worth can fluctuate over time due to various factors such as stock market changes and business ventures. - -app.add("SELECT * FROM table_name;", data_type='postgres', loader=postgres_loader) -# Adds `(1, 'What is your net worth, Elon Musk?', "As of October 2023, Elon Musk's net worth is $255.2 billion.")` - -response = app.query(question) -# Answer: As of October 2023, Elon Musk's net worth is $255.2 billion. -``` - -NOTE: The `add` function of the app will accept any executable query to load data. DO NOT pass the `CREATE`, `INSERT` queries in `add` function as they will result in not adding any data, so it is pointless. - -3. We automatically create a chunker to chunk your postgres data, however if you wish to provide your own chunker class. Here is how you can do that: -```Python - -from embedchain.chunkers.postgres import PostgresChunker -from embedchain.config.add_config import ChunkerConfig - -postgres_chunker_config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) -postgres_chunker = PostgresChunker(config=postgres_chunker_config) - -app.add("SELECT * FROM table_name;", data_type='postgres', loader=postgres_loader, chunker=postgres_chunker) -``` \ No newline at end of file diff --git a/embedchain/docs/components/data-sources/qna.mdx b/embedchain/docs/components/data-sources/qna.mdx deleted file mode 100644 index 3efaa47ff..000000000 --- a/embedchain/docs/components/data-sources/qna.mdx +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: '❓💬 Question and answer pair' ---- - -QnA pair is a local data type. To supply your own QnA pair, use the data_type as `qna_pair` and enter a tuple. Eg: - -```python -from embedchain import App - -app = App() - -app.add(("Question", "Answer"), data_type="qna_pair") -``` diff --git a/embedchain/docs/components/data-sources/sitemap.mdx b/embedchain/docs/components/data-sources/sitemap.mdx deleted file mode 100644 index 96b47ef1c..000000000 --- a/embedchain/docs/components/data-sources/sitemap.mdx +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: '🗺️ Sitemap' ---- - -Add all web pages from an xml-sitemap. Filters non-text files. Use the data_type as `sitemap`. Eg: - -```python -from embedchain import App - -app = App() - -app.add('https://example.com/sitemap.xml', data_type='sitemap') -``` \ No newline at end of file diff --git a/embedchain/docs/components/data-sources/slack.mdx b/embedchain/docs/components/data-sources/slack.mdx deleted file mode 100644 index 7b879fd6d..000000000 --- a/embedchain/docs/components/data-sources/slack.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: '🤖 Slack' ---- - -## Pre-requisite -- Download required packages by running `pip install --upgrade "embedchain[slack]"`. -- Configure your slack bot token as environment variable `SLACK_USER_TOKEN`. - - Find your user token on your [Slack Account](https://api.slack.com/authentication/token-types) - - Make sure your slack user token includes [search](https://api.slack.com/scopes/search:read) scope. - -## Example - -### Get Started - -This will automatically retrieve data from the workspace associated with the user's token. - -```python -import os -from embedchain import App - -os.environ["SLACK_USER_TOKEN"] = "xoxp-xxx" -app = App() - -app.add("in:general", data_type="slack") - -result = app.query("what are the messages in general channel?") - -print(result) -``` - - -### Customize your SlackLoader -1. Setup the Slack loader by configuring the Slack Webclient. -```Python -from embedchain.loaders.slack import SlackLoader - -os.environ["SLACK_USER_TOKEN"] = "xoxp-*" - -config = { - 'base_url': slack_app_url, - 'headers': web_headers, - 'team_id': slack_team_id, -} - -loader = SlackLoader(config) -``` - -NOTE: you can also pass the `config` with `base_url`, `headers`, `team_id` to setup your SlackLoader. - -2. Once you setup the loader, you can create an app and load data using the above slack loader -```Python -import os -from embedchain.pipeline import Pipeline as App - -app = App() - -app.add("in:random", data_type="slack", loader=loader) -question = "Which bots are available in the slack workspace's random channel?" -# Answer: The available bot in the slack workspace's random channel is the Embedchain bot. -``` - -3. We automatically create a chunker to chunk your slack data, however if you wish to provide your own chunker class. Here is how you can do that: -```Python -from embedchain.chunkers.slack import SlackChunker -from embedchain.config.add_config import ChunkerConfig - -slack_chunker_config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) -slack_chunker = SlackChunker(config=slack_chunker_config) - -app.add(slack_chunker, data_type="slack", loader=loader, chunker=slack_chunker) -``` \ No newline at end of file diff --git a/embedchain/docs/components/data-sources/substack.mdx b/embedchain/docs/components/data-sources/substack.mdx deleted file mode 100644 index dd10a9e7d..000000000 --- a/embedchain/docs/components/data-sources/substack.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "📝 Substack" ---- - -To add any Substack data sources to your app, just add the main base url as the source and set the data_type to `substack`. - -```python -from embedchain import App - -app = App() - -# source: for any substack just add the root URL -app.add('https://www.lennysnewsletter.com', data_type='substack') -app.query("Who is Brian Chesky?") -# Answer: Brian Chesky is the co-founder and CEO of Airbnb. -``` diff --git a/embedchain/docs/components/data-sources/text-file.mdx b/embedchain/docs/components/data-sources/text-file.mdx deleted file mode 100644 index 14b48c005..000000000 --- a/embedchain/docs/components/data-sources/text-file.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: '📄 Text file' ---- - -To add a .txt file, specify the data_type as `text_file`. The URL provided in the first parameter of the `add` function, should be a local path. Eg: - -```python -from embedchain import App - -app = App() -app.add('path/to/file.txt', data_type="text_file") - -app.query("Summarize the information of the text file") -``` \ No newline at end of file diff --git a/embedchain/docs/components/data-sources/text.mdx b/embedchain/docs/components/data-sources/text.mdx deleted file mode 100644 index 0fda6f573..000000000 --- a/embedchain/docs/components/data-sources/text.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: '📝 Text' ---- - -### Text - -Text is a local data type. To supply your own text, use the data_type as `text` and enter a string. The text is not processed, this can be very versatile. Eg: - -```python -from embedchain import App - -app = App() - -app.add('Seek wealth, not money or status. Wealth is having assets that earn while you sleep. Money is how we transfer time and wealth. Status is your place in the social hierarchy.', data_type='text') -``` - -Note: This is not used in the examples because in most cases you will supply a whole paragraph or file, which did not fit. diff --git a/embedchain/docs/components/data-sources/web-page.mdx b/embedchain/docs/components/data-sources/web-page.mdx deleted file mode 100644 index f4a50a923..000000000 --- a/embedchain/docs/components/data-sources/web-page.mdx +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: '🌐 HTML Web page' ---- - -To add any web page, use the data_type as `web_page`. Eg: - -```python -from embedchain import App - -app = App() - -app.add('a_valid_web_page_url', data_type='web_page') -``` diff --git a/embedchain/docs/components/data-sources/xml.mdx b/embedchain/docs/components/data-sources/xml.mdx deleted file mode 100644 index afe9a4124..000000000 --- a/embedchain/docs/components/data-sources/xml.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: '🧾 XML file' ---- - -### XML file - -To add any xml file, use the data_type as `xml`. Eg: - -```python -from embedchain import App - -app = App() - -app.add('content/data.xml') -``` - -Note: Only the text content of the xml file will be added to the app. The tags will be ignored. diff --git a/embedchain/docs/components/data-sources/youtube-channel.mdx b/embedchain/docs/components/data-sources/youtube-channel.mdx deleted file mode 100644 index d9f037ff0..000000000 --- a/embedchain/docs/components/data-sources/youtube-channel.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: '📽️ Youtube Channel' ---- - -## Setup - -Make sure you have all the required packages installed before using this data type. You can install them by running the following command in your terminal. - -```bash -pip install -U "embedchain[youtube]" -``` - -## Usage - -To add all the videos from a youtube channel to your app, use the data_type as `youtube_channel`. - -```python -from embedchain import App - -app = App() -app.add("@channel_name", data_type="youtube_channel") -``` diff --git a/embedchain/docs/components/data-sources/youtube-video.mdx b/embedchain/docs/components/data-sources/youtube-video.mdx deleted file mode 100644 index 01ac52406..000000000 --- a/embedchain/docs/components/data-sources/youtube-video.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: '📺 Youtube Video' ---- - -## Setup - -Make sure you have all the required packages installed before using this data type. You can install them by running the following command in your terminal. - -```bash -pip install -U "embedchain[youtube]" -``` - -## Usage - -To add any youtube video to your app, use the data_type as `youtube_video`. Eg: - -```python -from embedchain import App - -app = App() -app.add('a_valid_youtube_url_here', data_type='youtube_video') -``` diff --git a/embedchain/docs/components/embedding-models.mdx b/embedchain/docs/components/embedding-models.mdx deleted file mode 100644 index 7af84236b..000000000 --- a/embedchain/docs/components/embedding-models.mdx +++ /dev/null @@ -1,470 +0,0 @@ ---- -title: 🧩 Embedding models ---- - -## Overview - -Embedchain supports several embedding models from the following providers: - - - - - - - - - - - - - - - -## OpenAI - -To use OpenAI embedding function, you have to set the `OPENAI_API_KEY` environment variable. You can obtain the OpenAI API key from the [OpenAI Platform](https://platform.openai.com/account/api-keys). - -Once you have obtained the key, you can use it like this: - - - -```python main.py -import os -from embedchain import App - -os.environ['OPENAI_API_KEY'] = 'xxx' - -# load embedding model configuration from config.yaml file -app = App.from_config(config_path="config.yaml") - -app.add("https://en.wikipedia.org/wiki/OpenAI") -app.query("What is OpenAI?") -``` - -```yaml config.yaml -embedder: - provider: openai - config: - model: 'text-embedding-3-small' -``` - - - -* OpenAI announced two new embedding models: `text-embedding-3-small` and `text-embedding-3-large`. Embedchain supports both these models. Below you can find YAML config for both: - - - -```yaml text-embedding-3-small.yaml -embedder: - provider: openai - config: - model: 'text-embedding-3-small' -``` - -```yaml text-embedding-3-large.yaml -embedder: - provider: openai - config: - model: 'text-embedding-3-large' -``` - - - -## Google AI - -To use Google AI embedding function, you have to set the `GOOGLE_API_KEY` environment variable. You can obtain the Google API key from the [Google Maker Suite](https://makersuite.google.com/app/apikey) - - -```python main.py -import os -from embedchain import App - -os.environ["GOOGLE_API_KEY"] = "xxx" - -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -embedder: - provider: google - config: - model: 'models/embedding-001' - task_type: "retrieval_document" - title: "Embeddings for Embedchain" -``` - -
- -For more details regarding the Google AI embedding model, please refer to the [Google AI documentation](https://ai.google.dev/tutorials/python_quickstart#use_embeddings). - - -## AWS Bedrock - -To use AWS Bedrock embedding function, you have to set the AWS environment variable. - - -```python main.py -import os -from embedchain import App - -os.environ["AWS_ACCESS_KEY_ID"] = "xxx" -os.environ["AWS_SECRET_ACCESS_KEY"] = "xxx" -os.environ["AWS_REGION"] = "us-west-2" - -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -embedder: - provider: aws_bedrock - config: - model: 'amazon.titan-embed-text-v2:0' - vector_dimension: 1024 - task_type: "retrieval_document" - title: "Embeddings for Embedchain" -``` - -
- -For more details regarding the AWS Bedrock embedding model, please refer to the [AWS Bedrock documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/titan-embedding-models.html). - - -## Azure OpenAI - -To use Azure OpenAI embedding model, you have to set some of the azure openai related environment variables as given in the code block below: - - - -```python main.py -import os -from embedchain import App - -os.environ["OPENAI_API_TYPE"] = "azure" -os.environ["AZURE_OPENAI_ENDPOINT"] = "https://xxx.openai.azure.com/" -os.environ["AZURE_OPENAI_API_KEY"] = "xxx" -os.environ["OPENAI_API_VERSION"] = "xxx" - -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: azure_openai - config: - model: gpt-35-turbo - deployment_name: your_llm_deployment_name - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -embedder: - provider: azure_openai - config: - model: text-embedding-ada-002 - deployment_name: you_embedding_model_deployment_name -``` - - -You can find the list of models and deployment name on the [Azure OpenAI Platform](https://oai.azure.com/portal). - -## GPT4ALL - -GPT4All supports generating high quality embeddings of arbitrary length documents of text using a CPU optimized contrastively trained Sentence Transformer. - - - -```python main.py -from embedchain import App - -# load embedding model configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: gpt4all - config: - model: 'orca-mini-3b-gguf2-q4_0.gguf' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -embedder: - provider: gpt4all -``` - - - -## Hugging Face - -Hugging Face supports generating embeddings of arbitrary length documents of text using Sentence Transformer library. Example of how to generate embeddings using hugging face is given below: - - - -```python main.py -from embedchain import App - -# load embedding model configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: huggingface - config: - model: 'google/flan-t5-xxl' - temperature: 0.5 - max_tokens: 1000 - top_p: 0.5 - stream: false - -embedder: - provider: huggingface - config: - model: 'sentence-transformers/all-mpnet-base-v2' - model_kwargs: - trust_remote_code: True # Only use if you trust your embedder -``` - - - -## Vertex AI - -Embedchain supports Google's VertexAI embeddings model through a simple interface. You just have to pass the `model_name` in the config yaml and it would work out of the box. - - - -```python main.py -from embedchain import App - -# load embedding model configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: vertexai - config: - model: 'chat-bison' - temperature: 0.5 - top_p: 0.5 - -embedder: - provider: vertexai - config: - model: 'textembedding-gecko' -``` - - - -## NVIDIA AI - -[NVIDIA AI Foundation Endpoints](https://www.nvidia.com/en-us/ai-data-science/foundation-models/) let you quickly use NVIDIA's AI models, such as Mixtral 8x7B, Llama 2 etc, through our API. These models are available in the [NVIDIA NGC catalog](https://catalog.ngc.nvidia.com/ai-foundation-models), fully optimized and ready to use on NVIDIA's AI platform. They are designed for high speed and easy customization, ensuring smooth performance on any accelerated setup. - - -### Usage - -In order to use embedding models and LLMs from NVIDIA AI, create an account on [NVIDIA NGC Service](https://catalog.ngc.nvidia.com/). - -Generate an API key from their dashboard. Set the API key as `NVIDIA_API_KEY` environment variable. Note that the `NVIDIA_API_KEY` will start with `nvapi-`. - -Below is an example of how to use LLM model and embedding model from NVIDIA AI: - - - -```python main.py -import os -from embedchain import App - -os.environ['NVIDIA_API_KEY'] = 'nvapi-xxxx' - -config = { - "app": { - "config": { - "id": "my-app", - }, - }, - "llm": { - "provider": "nvidia", - "config": { - "model": "nemotron_steerlm_8b", - }, - }, - "embedder": { - "provider": "nvidia", - "config": { - "model": "nvolveqa_40k", - "vector_dimension": 1024, - }, - }, -} - -app = App.from_config(config=config) - -app.add("https://www.forbes.com/profile/elon-musk") -answer = app.query("What is the net worth of Elon Musk today?") -# Answer: The net worth of Elon Musk is subject to fluctuations based on the market value of his holdings in various companies. -# As of March 1, 2024, his net worth is estimated to be approximately $210 billion. However, this figure can change rapidly due to stock market fluctuations and other factors. -# Additionally, his net worth may include other assets such as real estate and art, which are not reflected in his stock portfolio. -``` - - - -## Cohere - -To use embedding models and LLMs from COHERE, create an account on [COHERE](https://dashboard.cohere.com/welcome/login?redirect_uri=%2Fapi-keys). - -Generate an API key from their dashboard. Set the API key as `COHERE_API_KEY` environment variable. - -Once you have obtained the key, you can use it like this: - - - -```python main.py -import os -from embedchain import App - -os.environ['COHERE_API_KEY'] = 'xxx' - -# load embedding model configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -embedder: - provider: cohere - config: - model: 'embed-english-light-v3.0' -``` - - - -* Cohere has few embedding models: `embed-english-v3.0`, `embed-multilingual-v3.0`, `embed-multilingual-light-v3.0`, `embed-english-v2.0`, `embed-english-light-v2.0` and `embed-multilingual-v2.0`. Embedchain supports all these models. Below you can find YAML config for all: - - - -```yaml embed-english-v3.0.yaml -embedder: - provider: cohere - config: - model: 'embed-english-v3.0' - vector_dimension: 1024 -``` - -```yaml embed-multilingual-v3.0.yaml -embedder: - provider: cohere - config: - model: 'embed-multilingual-v3.0' - vector_dimension: 1024 -``` - -```yaml embed-multilingual-light-v3.0.yaml -embedder: - provider: cohere - config: - model: 'embed-multilingual-light-v3.0' - vector_dimension: 384 -``` - -```yaml embed-english-v2.0.yaml -embedder: - provider: cohere - config: - model: 'embed-english-v2.0' - vector_dimension: 4096 -``` - -```yaml embed-english-light-v2.0.yaml -embedder: - provider: cohere - config: - model: 'embed-english-light-v2.0' - vector_dimension: 1024 -``` - -```yaml embed-multilingual-v2.0.yaml -embedder: - provider: cohere - config: - model: 'embed-multilingual-v2.0' - vector_dimension: 768 -``` - - - -## Ollama - -Ollama enables the use of embedding models, allowing you to generate high-quality embeddings directly on your local machine. Make sure to install [Ollama](https://ollama.com/download) and keep it running before using the embedding model. - -You can find the list of models at [Ollama Embedding Models](https://ollama.com/blog/embedding-models). - -Below is an example of how to use embedding model Ollama: - - - -```python main.py -import os -from embedchain import App - -# load embedding model configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -embedder: - provider: ollama - config: - model: 'all-minilm:latest' -``` - - - -## Clarifai - -Install related dependencies using the following command: - -```bash -pip install --upgrade 'embedchain[clarifai]' -``` - -set the `CLARIFAI_PAT` as environment variable which you can find in the [security page](https://clarifai.com/settings/security). Optionally you can also pass the PAT key as parameters in LLM/Embedder class. - -Now you are all set with exploring Embedchain. - - - -```python main.py -import os -from embedchain import App - -os.environ["CLARIFAI_PAT"] = "XXX" - -# load llm and embedder configuration from config.yaml file -app = App.from_config(config_path="config.yaml") - -#Now let's add some data. -app.add("https://www.forbes.com/profile/elon-musk") - -#Query the app -response = app.query("what college degrees does elon musk have?") -``` -Head to [Clarifai Platform](https://clarifai.com/explore/models?page=1&perPage=24&filterData=%5B%7B%22field%22%3A%22output_fields%22%2C%22value%22%3A%5B%22embeddings%22%5D%7D%5D) to explore all the State of the Art embedding models available to use. -For passing LLM model inference parameters use `model_kwargs` argument in the config file. Also you can use `api_key` argument to pass `CLARIFAI_PAT` in the config. - -```yaml config.yaml -llm: - provider: clarifai - config: - model: "https://clarifai.com/mistralai/completion/models/mistral-7B-Instruct" - model_kwargs: - temperature: 0.5 - max_tokens: 1000 -embedder: - provider: clarifai - config: - model: "https://clarifai.com/clarifai/main/models/BAAI-bge-base-en-v15" -``` - \ No newline at end of file diff --git a/embedchain/docs/components/evaluation.mdx b/embedchain/docs/components/evaluation.mdx deleted file mode 100644 index c1143d2ec..000000000 --- a/embedchain/docs/components/evaluation.mdx +++ /dev/null @@ -1,275 +0,0 @@ ---- -title: 🔬 Evaluation ---- - -## Overview - -We provide out-of-the-box evaluation metrics for your RAG application. You can use them to evaluate your RAG applications and compare against different settings of your production RAG application. - -Currently, we provide support for following evaluation metrics: - - - - - - - - -## Quickstart - -Here is a basic example of running evaluation: - -```python example.py -from embedchain import App - -app = App() - -# Add data sources -app.add("https://www.forbes.com/profile/elon-musk") - -# Run evaluation -app.evaluate(["What is the net worth of Elon Musk?", "How many companies Elon Musk owns?"]) -# {'answer_relevancy': 0.9987286412340826, 'groundedness': 1.0, 'context_relevancy': 0.3571428571428571} -``` - -Under the hood, Embedchain does the following: - -1. Runs semantic search in the vector database and fetches context -2. LLM call with question, context to fetch the answer -3. Run evaluation on following metrics: `context relevancy`, `groundedness`, and `answer relevancy` and return result - -## Advanced Usage - -We use OpenAI's `gpt-4` model as default LLM model for automatic evaluation. Hence, we require you to set `OPENAI_API_KEY` as an environment variable. - -### Step-1: Create dataset - -In order to evaluate your RAG application, you have to setup a dataset. A data point in the dataset consists of `questions`, `contexts`, `answer`. Here is an example of how to create a dataset for evaluation: - -```python -from embedchain.utils.eval import EvalData - -data = [ - { - "question": "What is the net worth of Elon Musk?", - "contexts": [ - "Elon Musk PROFILEElon MuskCEO, ...", - "a Twitter poll on whether the journalists' ...", - "2016 and run by Jared Birchall.[335]...", - ], - "answer": "As of the information provided, Elon Musk's net worth is $241.6 billion.", - }, - { - "question": "which companies does Elon Musk own?", - "contexts": [ - "of December 2023[update], ...", - "ThielCofounderView ProfileTeslaHolds ...", - "Elon Musk PROFILEElon MuskCEO, ...", - ], - "answer": "Elon Musk owns several companies, including Tesla, SpaceX, Neuralink, and The Boring Company.", - }, -] - -dataset = [] - -for d in data: - eval_data = EvalData(question=d["question"], contexts=d["contexts"], answer=d["answer"]) - dataset.append(eval_data) -``` - -### Step-2: Run evaluation - -Once you have created your dataset, you can run evaluation on the dataset by picking the metric you want to run evaluation on. - -For example, you can run evaluation on context relevancy metric using the following code: - -```python -from embedchain.evaluation.metrics import ContextRelevance -metric = ContextRelevance() -score = metric.evaluate(dataset) -print(score) -``` - -You can choose a different metric or write your own to run evaluation on. You can check the following links: - -- [Context Relevancy](#context_relevancy) -- [Answer relenvancy](#answer_relevancy) -- [Groundedness](#groundedness) -- [Build your own metric](#custom_metric) - -## Metrics - -### Context Relevancy - -Context relevancy is a metric to determine "how relevant the context is to the question". We use OpenAI's `gpt-4` model to determine the relevancy of the context. We achieve this by prompting the model with the question and the context and asking it to return relevant sentences from the context. We then use the following formula to determine the score: - -``` -context_relevance_score = num_relevant_sentences_in_context / num_of_sentences_in_context -``` - -#### Examples - -You can run the context relevancy evaluation with the following simple code: - -```python -from embedchain.evaluation.metrics import ContextRelevance - -metric = ContextRelevance() -score = metric.evaluate(dataset) # 'dataset' is definted in the create dataset section -print(score) -# 0.27975528364849833 -``` - -In the above example, we used sensible defaults for the evaluation. However, you can also configure the evaluation metric as per your needs using the `ContextRelevanceConfig` class. - -Here is a more advanced example of how to pass a custom evaluation config for evaluating on context relevance metric: - -```python -from embedchain.config.evaluation.base import ContextRelevanceConfig -from embedchain.evaluation.metrics import ContextRelevance - -eval_config = ContextRelevanceConfig(model="gpt-4", api_key="sk-xxx", language="en") -metric = ContextRelevance(config=eval_config) -metric.evaluate(dataset) -``` - -#### `ContextRelevanceConfig` - - - The model to use for the evaluation. Defaults to `gpt-4`. We only support openai's models for now. - - - The openai api key to use for the evaluation. Defaults to `None`. If not provided, we will use the `OPENAI_API_KEY` environment variable. - - - The language of the dataset being evaluated. We need this to determine the understand the context provided in the dataset. Defaults to `en`. - - - The prompt to extract the relevant sentences from the context. Defaults to `CONTEXT_RELEVANCY_PROMPT`, which can be found at `embedchain.config.evaluation.base` path. - - - -### Answer Relevancy - -Answer relevancy is a metric to determine how relevant the answer is to the question. We prompt the model with the answer and asking it to generate questions from the answer. We then use the cosine similarity between the generated questions and the original question to determine the score. - -``` -answer_relevancy_score = mean(cosine_similarity(generated_questions, original_question)) -``` - -#### Examples - -You can run the answer relevancy evaluation with the following simple code: - -```python -from embedchain.evaluation.metrics import AnswerRelevance - -metric = AnswerRelevance() -score = metric.evaluate(dataset) -print(score) -# 0.9505334177461916 -``` - -In the above example, we used sensible defaults for the evaluation. However, you can also configure the evaluation metric as per your needs using the `AnswerRelevanceConfig` class. Here is a more advanced example where you can provide your own evaluation config: - -```python -from embedchain.config.evaluation.base import AnswerRelevanceConfig -from embedchain.evaluation.metrics import AnswerRelevance - -eval_config = AnswerRelevanceConfig( - model='gpt-4', - embedder="text-embedding-ada-002", - api_key="sk-xxx", - num_gen_questions=2 -) -metric = AnswerRelevance(config=eval_config) -score = metric.evaluate(dataset) -``` - -#### `AnswerRelevanceConfig` - - - The model to use for the evaluation. Defaults to `gpt-4`. We only support openai's models for now. - - - The embedder to use for embedding the text. Defaults to `text-embedding-ada-002`. We only support openai's embedders for now. - - - The openai api key to use for the evaluation. Defaults to `None`. If not provided, we will use the `OPENAI_API_KEY` environment variable. - - - The number of questions to generate for each answer. We use the generated questions to compare the similarity with the original question to determine the score. Defaults to `1`. - - - The prompt to extract the `num_gen_questions` number of questions from the provided answer. Defaults to `ANSWER_RELEVANCY_PROMPT`, which can be found at `embedchain.config.evaluation.base` path. - - -## Groundedness - -Groundedness is a metric to determine how grounded the answer is to the context. We use OpenAI's `gpt-4` model to determine the groundedness of the answer. We achieve this by prompting the model with the answer and asking it to generate claims from the answer. We then again prompt the model with the context and the generated claims to determine the verdict on the claims. We then use the following formula to determine the score: - -``` -groundedness_score = (sum of all verdicts) / (total # of claims) -``` - -You can run the groundedness evaluation with the following simple code: - -```python -from embedchain.evaluation.metrics import Groundedness -metric = Groundedness() -score = metric.evaluate(dataset) # dataset from above -print(score) -# 1.0 -``` - -In the above example, we used sensible defaults for the evaluation. However, you can also configure the evaluation metric as per your needs using the `GroundednessConfig` class. Here is a more advanced example where you can configure the evaluation config: - -```python -from embedchain.config.evaluation.base import GroundednessConfig -from embedchain.evaluation.metrics import Groundedness - -eval_config = GroundednessConfig(model='gpt-4', api_key="sk-xxx") -metric = Groundedness(config=eval_config) -score = metric.evaluate(dataset) -``` - - -#### `GroundednessConfig` - - - The model to use for the evaluation. Defaults to `gpt-4`. We only support openai's models for now. - - - The openai api key to use for the evaluation. Defaults to `None`. If not provided, we will use the `OPENAI_API_KEY` environment variable. - - - The prompt to extract the claims from the provided answer. Defaults to `GROUNDEDNESS_ANSWER_CLAIMS_PROMPT`, which can be found at `embedchain.config.evaluation.base` path. - - - The prompt to get verdicts on the claims from the answer from the given context. Defaults to `GROUNDEDNESS_CLAIMS_INFERENCE_PROMPT`, which can be found at `embedchain.config.evaluation.base` path. - - -## Custom - -You can also create your own evaluation metric by extending the `BaseMetric` class. You can find the source code for the existing metrics at `embedchain.evaluation.metrics` path. - - -You must provide the `name` of your custom metric in the `__init__` method of your class. This name will be used to identify your metric in the evaluation report. - - -```python -from typing import Optional - -from embedchain.config.base_config import BaseConfig -from embedchain.evaluation.metrics import BaseMetric -from embedchain.utils.eval import EvalData - -class MyCustomMetric(BaseMetric): - def __init__(self, config: Optional[BaseConfig] = None): - super().__init__(name="my_custom_metric") - - def evaluate(self, dataset: list[EvalData]): - score = 0.0 - # write your evaluation logic here - return score -``` diff --git a/embedchain/docs/components/introduction.mdx b/embedchain/docs/components/introduction.mdx deleted file mode 100644 index 3f9122b5d..000000000 --- a/embedchain/docs/components/introduction.mdx +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: 🧩 Introduction ---- - -## Overview - -You can configure following components - -* [Data Source](/components/data-sources/overview) -* [LLM](/components/llms) -* [Embedding Model](/components/embedding-models) -* [Vector Database](/components/vector-databases) -* [Evaluation](/components/evaluation) diff --git a/embedchain/docs/components/llms.mdx b/embedchain/docs/components/llms.mdx deleted file mode 100644 index 183b8cd3f..000000000 --- a/embedchain/docs/components/llms.mdx +++ /dev/null @@ -1,899 +0,0 @@ ---- -title: 🤖 Large language models (LLMs) ---- - -## Overview - -Embedchain comes with built-in support for various popular large language models. We handle the complexity of integrating these models for you, allowing you to easily customize your language model interactions through a user-friendly interface. - - - - - - - - - - - - - - - - - - - - - - -## OpenAI - -To use OpenAI LLM models, you have to set the `OPENAI_API_KEY` environment variable. You can obtain the OpenAI API key from the [OpenAI Platform](https://platform.openai.com/account/api-keys). - -Once you have obtained the key, you can use it like this: - -```python -import os -from embedchain import App - -os.environ['OPENAI_API_KEY'] = 'xxx' - -app = App() -app.add("https://en.wikipedia.org/wiki/OpenAI") -app.query("What is OpenAI?") -``` - -If you are looking to configure the different parameters of the LLM, you can do so by loading the app using a [yaml config](https://github.com/embedchain/embedchain/blob/main/configs/chroma.yaml) file. - - - -```python main.py -import os -from embedchain import App - -os.environ['OPENAI_API_KEY'] = 'xxx' - -# load llm configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: openai - config: - model: 'gpt-4o-mini' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false -``` - - -### Function Calling -Embedchain supports OpenAI [Function calling](https://platform.openai.com/docs/guides/function-calling) with a single function. It accepts inputs in accordance with the [Langchain interface](https://python.langchain.com/docs/modules/model_io/chat/function_calling#legacy-args-functions-and-function_call). - - - ```python - from pydantic import BaseModel - - class multiply(BaseModel): - """Multiply two integers together.""" - - a: int = Field(..., description="First integer") - b: int = Field(..., description="Second integer") - ``` - - - - ```python - def multiply(a: int, b: int) -> int: - """Multiply two integers together. - - Args: - a: First integer - b: Second integer - """ - return a * b - ``` - - - ```python - multiply = { - "type": "function", - "function": { - "name": "multiply", - "description": "Multiply two integers together.", - "parameters": { - "type": "object", - "properties": { - "a": { - "description": "First integer", - "type": "integer" - }, - "b": { - "description": "Second integer", - "type": "integer" - } - }, - "required": [ - "a", - "b" - ] - } - } - } - ``` - - -With any of the previous inputs, the OpenAI LLM can be queried to provide the appropriate arguments for the function. - -```python -import os -from embedchain import App -from embedchain.llm.openai import OpenAILlm - -os.environ["OPENAI_API_KEY"] = "sk-xxx" - -llm = OpenAILlm(tools=multiply) -app = App(llm=llm) - -result = app.query("What is the result of 125 multiplied by fifteen?") -``` - -## Google AI - -To use Google AI model, you have to set the `GOOGLE_API_KEY` environment variable. You can obtain the Google API key from the [Google Maker Suite](https://makersuite.google.com/app/apikey) - - -```python main.py -import os -from embedchain import App - -os.environ["GOOGLE_API_KEY"] = "xxx" - -app = App.from_config(config_path="config.yaml") - -app.add("https://www.forbes.com/profile/elon-musk") - -response = app.query("What is the net worth of Elon Musk?") -if app.llm.config.stream: # if stream is enabled, response is a generator - for chunk in response: - print(chunk) -else: - print(response) -``` - -```yaml config.yaml -llm: - provider: google - config: - model: gemini-pro - max_tokens: 1000 - temperature: 0.5 - top_p: 1 - stream: false - -embedder: - provider: google - config: - model: 'models/embedding-001' - task_type: "retrieval_document" - title: "Embeddings for Embedchain" -``` - - -## Azure OpenAI - -To use Azure OpenAI model, you have to set some of the azure openai related environment variables as given in the code block below: - - - -```python main.py -import os -from embedchain import App - -os.environ["OPENAI_API_TYPE"] = "azure" -os.environ["AZURE_OPENAI_ENDPOINT"] = "https://xxx.openai.azure.com/" -os.environ["AZURE_OPENAI_KEY"] = "xxx" -os.environ["OPENAI_API_VERSION"] = "xxx" - -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: azure_openai - config: - model: gpt-4o-mini - deployment_name: your_llm_deployment_name - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -embedder: - provider: azure_openai - config: - model: text-embedding-ada-002 - deployment_name: you_embedding_model_deployment_name -``` - - -You can find the list of models and deployment name on the [Azure OpenAI Platform](https://oai.azure.com/portal). - -## Anthropic - -To use anthropic's model, please set the `ANTHROPIC_API_KEY` which you find on their [Account Settings Page](https://console.anthropic.com/account/keys). - - - -```python main.py -import os -from embedchain import App - -os.environ["ANTHROPIC_API_KEY"] = "xxx" - -# load llm configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: anthropic - config: - model: 'claude-instant-1' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false -``` - - - -## Cohere - -Install related dependencies using the following command: - -```bash -pip install --upgrade 'embedchain[cohere]' -``` - -Set the `COHERE_API_KEY` as environment variable which you can find on their [Account settings page](https://dashboard.cohere.com/api-keys). - -Once you have the API key, you are all set to use it with Embedchain. - - - -```python main.py -import os -from embedchain import App - -os.environ["COHERE_API_KEY"] = "xxx" - -# load llm configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: cohere - config: - model: large - temperature: 0.5 - max_tokens: 1000 - top_p: 1 -``` - - - -## Together - -Install related dependencies using the following command: - -```bash -pip install --upgrade 'embedchain[together]' -``` - -Set the `TOGETHER_API_KEY` as environment variable which you can find on their [Account settings page](https://api.together.xyz/settings/api-keys). - -Once you have the API key, you are all set to use it with Embedchain. - - - -```python main.py -import os -from embedchain import App - -os.environ["TOGETHER_API_KEY"] = "xxx" - -# load llm configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: together - config: - model: togethercomputer/RedPajama-INCITE-7B-Base - temperature: 0.5 - max_tokens: 1000 - top_p: 1 -``` - - - -## Ollama - -Setup Ollama using https://github.com/jmorganca/ollama - - - -```python main.py -import os -os.environ["OLLAMA_HOST"] = "http://127.0.0.1:11434" -from embedchain import App - -# load llm configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: ollama - config: - model: 'llama2' - temperature: 0.5 - top_p: 1 - stream: true - base_url: 'http://localhost:11434' -embedder: - provider: ollama - config: - model: znbang/bge:small-en-v1.5-q8_0 - base_url: http://localhost:11434 - -``` - - - - -## vLLM - -Setup vLLM by following instructions given in [their docs](https://docs.vllm.ai/en/latest/getting_started/installation.html). - - - -```python main.py -import os -from embedchain import App - -# load llm configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: vllm - config: - model: 'meta-llama/Llama-2-70b-hf' - temperature: 0.5 - top_p: 1 - top_k: 10 - stream: true - trust_remote_code: true -``` - - - -## Clarifai - -Install related dependencies using the following command: - -```bash -pip install --upgrade 'embedchain[clarifai]' -``` - -set the `CLARIFAI_PAT` as environment variable which you can find in the [security page](https://clarifai.com/settings/security). Optionally you can also pass the PAT key as parameters in LLM/Embedder class. - -Now you are all set with exploring Embedchain. - - - -```python main.py -import os -from embedchain import App - -os.environ["CLARIFAI_PAT"] = "XXX" - -# load llm configuration from config.yaml file -app = App.from_config(config_path="config.yaml") - -#Now let's add some data. -app.add("https://www.forbes.com/profile/elon-musk") - -#Query the app -response = app.query("what college degrees does elon musk have?") -``` -Head to [Clarifai Platform](https://clarifai.com/explore/models?page=1&perPage=24&filterData=%5B%7B%22field%22%3A%22use_cases%22%2C%22value%22%3A%5B%22llm%22%5D%7D%5D) to browse various State-of-the-Art LLM models for your use case. -For passing model inference parameters use `model_kwargs` argument in the config file. Also you can use `api_key` argument to pass `CLARIFAI_PAT` in the config. - -```yaml config.yaml -llm: - provider: clarifai - config: - model: "https://clarifai.com/mistralai/completion/models/mistral-7B-Instruct" - model_kwargs: - temperature: 0.5 - max_tokens: 1000 -embedder: - provider: clarifai - config: - model: "https://clarifai.com/clarifai/main/models/BAAI-bge-base-en-v15" -``` - - - -## GPT4ALL - -Install related dependencies using the following command: - -```bash -pip install --upgrade 'embedchain[opensource]' -``` - -GPT4all is a free-to-use, locally running, privacy-aware chatbot. No GPU or internet required. You can use this with Embedchain using the following code: - - - -```python main.py -from embedchain import App - -# load llm configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: gpt4all - config: - model: 'orca-mini-3b-gguf2-q4_0.gguf' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -embedder: - provider: gpt4all -``` - - - -## JinaChat - -First, set `JINACHAT_API_KEY` in environment variable which you can obtain from [their platform](https://chat.jina.ai/api). - -Once you have the key, load the app using the config yaml file: - - - -```python main.py -import os -from embedchain import App - -os.environ["JINACHAT_API_KEY"] = "xxx" -# load llm configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: jina - config: - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false -``` - - - -## Hugging Face - - -Install related dependencies using the following command: - -```bash -pip install --upgrade 'embedchain[huggingface-hub]' -``` - -First, set `HUGGINGFACE_ACCESS_TOKEN` in environment variable which you can obtain from [their platform](https://huggingface.co/settings/tokens). - -You can load the LLMs from Hugging Face using three ways: - -- [Hugging Face Hub](#hugging-face-hub) -- [Hugging Face Local Pipelines](#hugging-face-local-pipelines) -- [Hugging Face Inference Endpoint](#hugging-face-inference-endpoint) - -### Hugging Face Hub - -To load the model from Hugging Face Hub, use the following code: - - - -```python main.py -import os -from embedchain import App - -os.environ["HUGGINGFACE_ACCESS_TOKEN"] = "xxx" - -config = { - "app": {"config": {"id": "my-app"}}, - "llm": { - "provider": "huggingface", - "config": { - "model": "bigscience/bloom-1b7", - "top_p": 0.5, - "max_length": 200, - "temperature": 0.1, - }, - }, -} - -app = App.from_config(config=config) -``` - - -### Hugging Face Local Pipelines - -If you want to load the locally downloaded model from Hugging Face, you can do so by following the code provided below: - - -```python main.py -from embedchain import App - -config = { - "app": {"config": {"id": "my-app"}}, - "llm": { - "provider": "huggingface", - "config": { - "model": "Trendyol/Trendyol-LLM-7b-chat-v0.1", - "local": True, # Necessary if you want to run model locally - "top_p": 0.5, - "max_tokens": 1000, - "temperature": 0.1, - }, - } -} -app = App.from_config(config=config) -``` - - -### Hugging Face Inference Endpoint - -You can also use [Hugging Face Inference Endpoints](https://huggingface.co/docs/inference-endpoints/index#-inference-endpoints) to access custom endpoints. First, set the `HUGGINGFACE_ACCESS_TOKEN` as above. - -Then, load the app using the config yaml file: - - - -```python main.py -from embedchain import App - -config = { - "app": {"config": {"id": "my-app"}}, - "llm": { - "provider": "huggingface", - "config": { - "endpoint": "https://api-inference.huggingface.co/models/gpt2", - "model_params": {"temprature": 0.1, "max_new_tokens": 100} - }, - }, -} -app = App.from_config(config=config) - -``` - - -Currently only supports `text-generation` and `text2text-generation` for now [[ref](https://api.python.langchain.com/en/latest/llms/langchain_community.llms.huggingface_endpoint.HuggingFaceEndpoint.html?highlight=huggingfaceendpoint#)]. - -See langchain's [hugging face endpoint](https://python.langchain.com/docs/integrations/chat/huggingface#huggingfaceendpoint) for more information. - -## Llama2 - -Llama2 is integrated through [Replicate](https://replicate.com/). Set `REPLICATE_API_TOKEN` in environment variable which you can obtain from [their platform](https://replicate.com/account/api-tokens). - -Once you have the token, load the app using the config yaml file: - - - -```python main.py -import os -from embedchain import App - -os.environ["REPLICATE_API_TOKEN"] = "xxx" - -# load llm configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: llama2 - config: - model: 'a16z-infra/llama13b-v2-chat:df7690f1994d94e96ad9d568eac121aecf50684a0b0963b25a41cc40061269e5' - temperature: 0.5 - max_tokens: 1000 - top_p: 0.5 - stream: false -``` - - -## Vertex AI - -Setup Google Cloud Platform application credentials by following the instruction on [GCP](https://cloud.google.com/docs/authentication/external/set-up-adc). Once setup is done, use the following code to create an app using VertexAI as provider: - - - -```python main.py -from embedchain import App - -# load llm configuration from config.yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: vertexai - config: - model: 'chat-bison' - temperature: 0.5 - top_p: 0.5 -``` - - - -## Mistral AI - -Obtain the Mistral AI api key from their [console](https://console.mistral.ai/). - - - - ```python main.py -os.environ["MISTRAL_API_KEY"] = "xxx" - -app = App.from_config(config_path="config.yaml") - -app.add("https://www.forbes.com/profile/elon-musk") - -response = app.query("what is the net worth of Elon Musk?") -# As of January 16, 2024, Elon Musk's net worth is $225.4 billion. - -response = app.chat("which companies does elon own?") -# Elon Musk owns Tesla, SpaceX, Boring Company, Twitter, and X. - -response = app.chat("what question did I ask you already?") -# You have asked me several times already which companies Elon Musk owns, specifically Tesla, SpaceX, Boring Company, Twitter, and X. -``` - -```yaml config.yaml -llm: - provider: mistralai - config: - model: mistral-tiny - temperature: 0.5 - max_tokens: 1000 - top_p: 1 -embedder: - provider: mistralai - config: - model: mistral-embed -``` - - - -## AWS Bedrock - -### Setup -- Before using the AWS Bedrock LLM, make sure you have the appropriate model access from [Bedrock Console](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/modelaccess). -- You will also need to authenticate the `boto3` client by using a method in the [AWS documentation](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#configuring-credentials) -- You can optionally export an `AWS_REGION` - - -### Usage - - - -```python main.py -import os -from embedchain import App - -os.environ["AWS_REGION"] = "us-west-2" - -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -llm: - provider: aws_bedrock - config: - model: amazon.titan-text-express-v1 - # check notes below for model_kwargs - model_kwargs: - temperature: 0.5 - topP: 1 - maxTokenCount: 1000 -``` - - -
- - The model arguments are different for each providers. Please refer to the [AWS Bedrock Documentation](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers) to find the appropriate arguments for your model. - - -
- -## Groq - -[Groq](https://groq.com/) is the creator of the world's first Language Processing Unit (LPU), providing exceptional speed performance for AI workloads running on their LPU Inference Engine. - - -### Usage - -In order to use LLMs from Groq, go to their [platform](https://console.groq.com/keys) and get the API key. - -Set the API key as `GROQ_API_KEY` environment variable or pass in your app configuration to use the model as given below in the example. - - - -```python main.py -import os -from embedchain import App - -# Set your API key here or pass as the environment variable -groq_api_key = "gsk_xxxx" - -config = { - "llm": { - "provider": "groq", - "config": { - "model": "mixtral-8x7b-32768", - "api_key": groq_api_key, - "stream": True - } - } -} - -app = App.from_config(config=config) -# Add your data source here -app.add("https://docs.embedchain.ai/sitemap.xml", data_type="sitemap") -app.query("Write a poem about Embedchain") - -# In the realm of data, vast and wide, -# Embedchain stands with knowledge as its guide. -# A platform open, for all to try, -# Building bots that can truly fly. - -# With REST API, data in reach, -# Deployment a breeze, as easy as a speech. -# Updating data sources, anytime, anyday, -# Embedchain's power, never sway. - -# A knowledge base, an assistant so grand, -# Connecting to platforms, near and far. -# Discord, WhatsApp, Slack, and more, -# Embedchain's potential, never a bore. -``` - - -## NVIDIA AI - -[NVIDIA AI Foundation Endpoints](https://www.nvidia.com/en-us/ai-data-science/foundation-models/) let you quickly use NVIDIA's AI models, such as Mixtral 8x7B, Llama 2 etc, through our API. These models are available in the [NVIDIA NGC catalog](https://catalog.ngc.nvidia.com/ai-foundation-models), fully optimized and ready to use on NVIDIA's AI platform. They are designed for high speed and easy customization, ensuring smooth performance on any accelerated setup. - - -### Usage - -In order to use LLMs from NVIDIA AI, create an account on [NVIDIA NGC Service](https://catalog.ngc.nvidia.com/). - -Generate an API key from their dashboard. Set the API key as `NVIDIA_API_KEY` environment variable. Note that the `NVIDIA_API_KEY` will start with `nvapi-`. - -Below is an example of how to use LLM model and embedding model from NVIDIA AI: - - - -```python main.py -import os -from embedchain import App - -os.environ['NVIDIA_API_KEY'] = 'nvapi-xxxx' - -config = { - "app": { - "config": { - "id": "my-app", - }, - }, - "llm": { - "provider": "nvidia", - "config": { - "model": "nemotron_steerlm_8b", - }, - }, - "embedder": { - "provider": "nvidia", - "config": { - "model": "nvolveqa_40k", - "vector_dimension": 1024, - }, - }, -} - -app = App.from_config(config=config) - -app.add("https://www.forbes.com/profile/elon-musk") -answer = app.query("What is the net worth of Elon Musk today?") -# Answer: The net worth of Elon Musk is subject to fluctuations based on the market value of his holdings in various companies. -# As of March 1, 2024, his net worth is estimated to be approximately $210 billion. However, this figure can change rapidly due to stock market fluctuations and other factors. -# Additionally, his net worth may include other assets such as real estate and art, which are not reflected in his stock portfolio. -``` - - -## Token Usage - -You can get the cost of the query by setting `token_usage` to `True` in the config file. This will return the token details: `prompt_tokens`, `completion_tokens`, `total_tokens`, `total_cost`, `cost_currency`. -The list of paid LLMs that support token usage are: -- OpenAI -- Vertex AI -- Anthropic -- Cohere -- Together -- Groq -- Mistral AI -- NVIDIA AI - -Here is an example of how to use token usage: - - -```python main.py -os.environ["OPENAI_API_KEY"] = "xxx" - -app = App.from_config(config_path="config.yaml") - -app.add("https://www.forbes.com/profile/elon-musk") - -response = app.query("what is the net worth of Elon Musk?") -# {'answer': 'Elon Musk's net worth is $209.9 billion as of 6/9/24.', -# 'usage': {'prompt_tokens': 1228, -# 'completion_tokens': 21, -# 'total_tokens': 1249, -# 'total_cost': 0.001884, -# 'cost_currency': 'USD'} -# } - - -response = app.chat("Which companies did Elon Musk found?") -# {'answer': 'Elon Musk founded six companies, including Tesla, which is an electric car maker, SpaceX, a rocket producer, and the Boring Company, a tunneling startup.', -# 'usage': {'prompt_tokens': 1616, -# 'completion_tokens': 34, -# 'total_tokens': 1650, -# 'total_cost': 0.002492, -# 'cost_currency': 'USD'} -# } -``` - -```yaml config.yaml -llm: - provider: openai - config: - model: gpt-4o-mini - temperature: 0.5 - max_tokens: 1000 - token_usage: true -``` - - -If a model is missing and you'd like to add it to `model_prices_and_context_window.json`, please feel free to open a PR. - -
- - diff --git a/embedchain/docs/components/retrieval-methods.mdx b/embedchain/docs/components/retrieval-methods.mdx deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/docs/components/vector-databases.mdx b/embedchain/docs/components/vector-databases.mdx deleted file mode 100644 index c889e1054..000000000 --- a/embedchain/docs/components/vector-databases.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: 🗄️ Vector databases ---- - -## Overview - -Utilizing a vector database alongside Embedchain is a seamless process. All you need to do is configure it within the YAML configuration file. We've provided examples for each supported database below: - - - - - - - - - - - - - diff --git a/embedchain/docs/components/vector-databases/chromadb.mdx b/embedchain/docs/components/vector-databases/chromadb.mdx deleted file mode 100644 index 783dfe890..000000000 --- a/embedchain/docs/components/vector-databases/chromadb.mdx +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: ChromaDB ---- - - - -```python main.py -from embedchain import App - -# load chroma configuration from yaml file -app = App.from_config(config_path="config1.yaml") -``` - -```yaml config1.yaml -vectordb: - provider: chroma - config: - collection_name: 'my-collection' - dir: db - allow_reset: true -``` - -```yaml config2.yaml -vectordb: - provider: chroma - config: - collection_name: 'my-collection' - host: localhost - port: 5200 - allow_reset: true -``` - - - - diff --git a/embedchain/docs/components/vector-databases/elasticsearch.mdx b/embedchain/docs/components/vector-databases/elasticsearch.mdx deleted file mode 100644 index 0a354e65f..000000000 --- a/embedchain/docs/components/vector-databases/elasticsearch.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Elasticsearch ---- - -Install related dependencies using the following command: - -```bash -pip install --upgrade 'embedchain[elasticsearch]' -``` - - -You can configure the Elasticsearch connection by providing either `es_url` or `cloud_id`. If you are using the Elasticsearch Service on Elastic Cloud, you can find the `cloud_id` on the [Elastic Cloud dashboard](https://cloud.elastic.co/deployments). - - -You can authorize the connection to Elasticsearch by providing either `basic_auth`, `api_key`, or `bearer_auth`. - - - -```python main.py -from embedchain import App - -# load elasticsearch configuration from yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -vectordb: - provider: elasticsearch - config: - collection_name: 'es-index' - cloud_id: 'deployment-name:xxxx' - basic_auth: - - elastic - - - verify_certs: false -``` - - - diff --git a/embedchain/docs/components/vector-databases/lancedb.mdx b/embedchain/docs/components/vector-databases/lancedb.mdx deleted file mode 100644 index 97af57dfe..000000000 --- a/embedchain/docs/components/vector-databases/lancedb.mdx +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: LanceDB ---- - -## Install Embedchain with LanceDB - -Install Embedchain, LanceDB and related dependencies using the following command: - -```bash -pip install "embedchain[lancedb]" -``` - -LanceDB is a developer-friendly, open source database for AI. From hyper scalable vector search and advanced retrieval for RAG, to streaming training data and interactive exploration of large scale AI datasets. -In order to use LanceDB as vector database, not need to set any key for local use. - -### With OPENAI - - -```python main.py -import os -from embedchain import App - -# set OPENAI_API_KEY as env variable -os.environ["OPENAI_API_KEY"] = "sk-xxx" - -# create Embedchain App and set config -app = App.from_config(config={ - "vectordb": { - "provider": "lancedb", - "config": { - "collection_name": "lancedb-index" - } - } - } -) - -# add data source and start query in -app.add("https://www.forbes.com/profile/elon-musk") - -# query continuously -while(True): - question = input("Enter question: ") - if question in ['q', 'exit', 'quit']: - break - answer = app.query(question) - print(answer) -``` - - - -### With Local LLM - - -```python main.py -from embedchain import Pipeline as App - -# config for Embedchain App -config = { - 'llm': { - 'provider': 'huggingface', - 'config': { - 'model': 'mistralai/Mistral-7B-v0.1', - 'temperature': 0.1, - 'max_tokens': 250, - 'top_p': 0.1, - 'stream': True - } - }, - 'embedder': { - 'provider': 'huggingface', - 'config': { - 'model': 'sentence-transformers/all-mpnet-base-v2' - } - }, - 'vectordb': { - 'provider': 'lancedb', - 'config': { - 'collection_name': 'lancedb-index' - } - } -} - -app = App.from_config(config=config) - -# add data source and start query in -app.add("https://www.tesla.com/ns_videos/2022-tesla-impact-report.pdf") - -# query continuously -while(True): - question = input("Enter question: ") - if question in ['q', 'exit', 'quit']: - break - answer = app.query(question) - print(answer) -``` - - - - - \ No newline at end of file diff --git a/embedchain/docs/components/vector-databases/opensearch.mdx b/embedchain/docs/components/vector-databases/opensearch.mdx deleted file mode 100644 index 8f6866977..000000000 --- a/embedchain/docs/components/vector-databases/opensearch.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: OpenSearch ---- - -Install related dependencies using the following command: - -```bash -pip install --upgrade 'embedchain[opensearch]' -``` - - - -```python main.py -from embedchain import App - -# load opensearch configuration from yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -vectordb: - provider: opensearch - config: - collection_name: 'my-app' - opensearch_url: 'https://localhost:9200' - http_auth: - - admin - - admin - vector_dimension: 1536 - use_ssl: false - verify_certs: false -``` - - - - diff --git a/embedchain/docs/components/vector-databases/pinecone.mdx b/embedchain/docs/components/vector-databases/pinecone.mdx deleted file mode 100644 index d21ebfeac..000000000 --- a/embedchain/docs/components/vector-databases/pinecone.mdx +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: Pinecone ---- - -## Overview - -Install pinecone related dependencies using the following command: - -```bash -pip install --upgrade 'pinecone-client pinecone-text' -``` - -In order to use Pinecone as vector database, set the environment variable `PINECONE_API_KEY` which you can find on [Pinecone dashboard](https://app.pinecone.io/). - - - -```python main.py -from embedchain import App - -# Load pinecone configuration from yaml file -app = App.from_config(config_path="pod_config.yaml") -# Or -app = App.from_config(config_path="serverless_config.yaml") -``` - -```yaml pod_config.yaml -vectordb: - provider: pinecone - config: - metric: cosine - vector_dimension: 1536 - index_name: my-pinecone-index - pod_config: - environment: gcp-starter - metadata_config: - indexed: - - "url" - - "hash" -``` - -```yaml serverless_config.yaml -vectordb: - provider: pinecone - config: - metric: cosine - vector_dimension: 1536 - index_name: my-pinecone-index - serverless_config: - cloud: aws - region: us-west-2 -``` - - - -
- -You can find more information about Pinecone configuration [here](https://docs.pinecone.io/docs/manage-indexes#create-a-pod-based-index). -You can also optionally provide `index_name` as a config param in yaml file to specify the index name. If not provided, the index name will be `{collection_name}-{vector_dimension}`. - - -## Usage - -### Hybrid search - -Here is an example of how you can do hybrid search using Pinecone as a vector database through Embedchain. - -```python -import os - -from embedchain import App - -config = { - 'app': { - "config": { - "id": "ec-docs-hybrid-search" - } - }, - 'vectordb': { - 'provider': 'pinecone', - 'config': { - 'metric': 'dotproduct', - 'vector_dimension': 1536, - 'index_name': 'my-index', - 'serverless_config': { - 'cloud': 'aws', - 'region': 'us-west-2' - }, - 'hybrid_search': True, # Remember to set this for hybrid search - } - } -} - -# Initialize app -app = App.from_config(config=config) - -# Add documents -app.add("/path/to/file.pdf", data_type="pdf_file", namespace="my-namespace") - -# Query -app.query("", namespace="my-namespace") - -# Chat -app.chat("", namespace="my-namespace") -``` - -Under the hood, Embedchain fetches the relevant chunks from the documents you added by doing hybrid search on the pinecone index. -If you have questions on how pinecone hybrid search works, please refer to their [offical documentation here](https://docs.pinecone.io/docs/hybrid-search). - - diff --git a/embedchain/docs/components/vector-databases/qdrant.mdx b/embedchain/docs/components/vector-databases/qdrant.mdx deleted file mode 100644 index cadb42e92..000000000 --- a/embedchain/docs/components/vector-databases/qdrant.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Qdrant ---- - -In order to use Qdrant as a vector database, set the environment variables `QDRANT_URL` and `QDRANT_API_KEY` which you can find on [Qdrant Dashboard](https://cloud.qdrant.io/). - - -```python main.py -from embedchain import App - -# load qdrant configuration from yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -vectordb: - provider: qdrant - config: - collection_name: my_qdrant_index -``` - - - diff --git a/embedchain/docs/components/vector-databases/weaviate.mdx b/embedchain/docs/components/vector-databases/weaviate.mdx deleted file mode 100644 index e5b1d5eda..000000000 --- a/embedchain/docs/components/vector-databases/weaviate.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Weaviate ---- - - -In order to use Weaviate as a vector database, set the environment variables `WEAVIATE_ENDPOINT` and `WEAVIATE_API_KEY` which you can find on [Weaviate dashboard](https://console.weaviate.cloud/dashboard). - - -```python main.py -from embedchain import App - -# load weaviate configuration from yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -vectordb: - provider: weaviate - config: - collection_name: my_weaviate_index -``` - - - diff --git a/embedchain/docs/components/vector-databases/zilliz.mdx b/embedchain/docs/components/vector-databases/zilliz.mdx deleted file mode 100644 index 55c0dbaa7..000000000 --- a/embedchain/docs/components/vector-databases/zilliz.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Zilliz ---- - -Install related dependencies using the following command: - -```bash -pip install --upgrade 'embedchain[milvus]' -``` - -Set the Zilliz environment variables `ZILLIZ_CLOUD_URI` and `ZILLIZ_CLOUD_TOKEN` which you can find it on their [cloud platform](https://cloud.zilliz.com/). - - - -```python main.py -import os -from embedchain import App - -os.environ['ZILLIZ_CLOUD_URI'] = 'https://xxx.zillizcloud.com' -os.environ['ZILLIZ_CLOUD_TOKEN'] = 'xxx' - -# load zilliz configuration from yaml file -app = App.from_config(config_path="config.yaml") -``` - -```yaml config.yaml -vectordb: - provider: zilliz - config: - collection_name: 'zilliz_app' - uri: https://xxxx.api.gcp-region.zillizcloud.com - token: xxx - vector_dim: 1536 - metric_type: L2 -``` - - - - diff --git a/embedchain/docs/contribution/dev.mdx b/embedchain/docs/contribution/dev.mdx deleted file mode 100644 index 3ce71c25c..000000000 --- a/embedchain/docs/contribution/dev.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: '👨‍💻 Development' -description: 'Contribute to Embedchain framework development' ---- - -Thank you for your interest in contributing to the EmbedChain project! We welcome your ideas and contributions to help improve the project. Please follow the instructions below to get started: - -1. **Fork the repository**: Click on the "Fork" button at the top right corner of this repository page. This will create a copy of the repository in your own GitHub account. - -2. **Install the required dependencies**: Ensure that you have the necessary dependencies installed in your Python environment. You can do this by running the following command: - -```bash -make install -``` - -3. **Make changes in the code**: Create a new branch in your forked repository and make your desired changes in the codebase. -4. **Format code**: Before creating a pull request, it's important to ensure that your code follows our formatting guidelines. Run the following commands to format the code: - -```bash -make lint format -``` - -5. **Create a pull request**: When you are ready to contribute your changes, submit a pull request to the EmbedChain repository. Provide a clear and descriptive title for your pull request, along with a detailed description of the changes you have made. - -## Team - -### Authors - -- Taranjeet Singh ([@taranjeetio](https://twitter.com/taranjeetio)) -- Deshraj Yadav ([@deshrajdry](https://twitter.com/deshrajdry)) - -### Citation - -If you utilize this repository, please consider citing it with: - -``` -@misc{embedchain, - author = {Taranjeet Singh, Deshraj Yadav}, - title = {Embechain: The Open Source RAG Framework}, - year = {2023}, - publisher = {GitHub}, - journal = {GitHub repository}, - howpublished = {\url{https://github.com/embedchain/embedchain}}, -} -``` diff --git a/embedchain/docs/contribution/docs.mdx b/embedchain/docs/contribution/docs.mdx deleted file mode 100644 index 7aa846ec5..000000000 --- a/embedchain/docs/contribution/docs.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: '📝 Documentation' -description: 'Contribute to Embedchain docs' ---- - - - **Prerequisite** You should have installed Node.js (version 18.10.0 or - higher). - - -Step 1. Install Mintlify on your OS: - - - -```bash npm -npm i -g mintlify -``` - -```bash yarn -yarn global add mintlify -``` - - - -Step 2. Go to the `docs/` directory (where you can find `mint.json`) and run the following command: - -```bash -mintlify dev -``` - -The documentation website is now available at `http://localhost:3000`. - -### Custom Ports - -Mintlify uses port 3000 by default. You can use the `--port` flag to customize the port Mintlify runs on. For example, use this command to run in port 3333: - -```bash -mintlify dev --port 3333 -``` - -You will see an error like this if you try to run Mintlify in a port that's already taken: - -```md -Error: listen EADDRINUSE: address already in use :::3000 -``` - -## Mintlify Versions - -Each CLI is linked to a specific version of Mintlify. Please update the CLI if your local website looks different than production. - - - -```bash npm -npm i -g mintlify@latest -``` - -```bash yarn -yarn global upgrade mintlify -``` - - diff --git a/embedchain/docs/contribution/guidelines.mdx b/embedchain/docs/contribution/guidelines.mdx deleted file mode 100644 index 3c5d557eb..000000000 --- a/embedchain/docs/contribution/guidelines.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: '📋 Guidelines' -url: https://github.com/mem0ai/mem0/blob/main/embedchain/CONTRIBUTING.md ---- \ No newline at end of file diff --git a/embedchain/docs/contribution/python.mdx b/embedchain/docs/contribution/python.mdx deleted file mode 100644 index 47bc84c27..000000000 --- a/embedchain/docs/contribution/python.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: '🐍 Python' -url: https://github.com/embedchain/embedchain ---- \ No newline at end of file diff --git a/embedchain/docs/deployment/fly_io.mdx b/embedchain/docs/deployment/fly_io.mdx deleted file mode 100644 index ed8992915..000000000 --- a/embedchain/docs/deployment/fly_io.mdx +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: 'Fly.io' -description: 'Deploy your RAG application to fly.io platform' ---- - -Embedchain has a nice and simple abstraction on top of the [Fly.io](https://fly.io/) tools to let developers deploy RAG application to fly.io platform seamlessly. - -Follow the instructions given below to deploy your first application quickly: - - -## Step-1: Install flyctl command line - - -```bash OSX -brew install flyctl -``` - -```bash Linux -curl -L https://fly.io/install.sh | sh -``` - -```bash Windows -pwsh -Command "iwr https://fly.io/install.ps1 -useb | iex" -``` - - -Once you have installed the fly.io cli tool, signup/login to their platform using the following command: - - -```bash Sign up -fly auth signup -``` - -```bash Sign in -fly auth login -``` - - -In case you run into issues, refer to official [fly.io docs](https://fly.io/docs/hands-on/install-flyctl/). - -## Step-2: Create RAG app - -We provide a command line utility called `ec` in embedchain that inherits the template for `fly.io` platform and help you deploy the app. Follow the instructions to create a fly.io app using the template provided: - -```bash Install embedchain -pip install embedchain -``` - -```bash Create application -mkdir my-rag-app -ec create --template=fly.io -``` - -This will generate a directory structure like this: - -```bash -├── Dockerfile -├── app.py -├── fly.toml -├── .env -├── .env.example -├── embedchain.json -└── requirements.txt -``` - -Feel free to edit the files as required. -- `Dockerfile`: Defines the steps to setup the application -- `app.py`: Contains API app code -- `fly.toml`: fly.io config file -- `.env`: Contains environment variables for production -- `.env.example`: Contains dummy environment variables (can ignore this file) -- `embedchain.json`: Contains embedchain specific configuration for deployment (you don't need to configure this) -- `requirements.txt`: Contains python dependencies for your application - -## Step-3: Test app locally - -You can run the app locally by simply doing: - -```bash Run locally -pip install -r requirements.txt -ec dev -``` - -## Step-4: Deploy to fly.io - -You can deploy to fly.io using the following command: -```bash Deploy app -ec deploy -``` - -Once this step finished, it will provide you with the deployment endpoint where you can access the app live. It will look something like this (Swagger docs): - -You can also check the logs, monitor app status etc on their dashboard by running command `fly dashboard`. - - - -## Seeking help? - -If you run into issues with deployment, please feel free to reach out to us via any of the following methods: - - diff --git a/embedchain/docs/deployment/gradio_app.mdx b/embedchain/docs/deployment/gradio_app.mdx deleted file mode 100644 index 6c79aa208..000000000 --- a/embedchain/docs/deployment/gradio_app.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: 'Gradio.app' -description: 'Deploy your RAG application to gradio.app platform' ---- - -Embedchain offers a Streamlit template to facilitate the development of RAG chatbot applications in just three easy steps. - -Follow the instructions given below to deploy your first application quickly: - -## Step-1: Create RAG app - -We provide a command line utility called `ec` in embedchain that inherits the template for `gradio.app` platform and help you deploy the app. Follow the instructions to create a gradio.app app using the template provided: - -```bash Install embedchain -pip install embedchain -``` - -```bash Create application -mkdir my-rag-app -ec create --template=gradio.app -``` - -This will generate a directory structure like this: - -```bash -├── app.py -├── embedchain.json -└── requirements.txt -``` - -Feel free to edit the files as required. -- `app.py`: Contains API app code -- `embedchain.json`: Contains embedchain specific configuration for deployment (you don't need to configure this) -- `requirements.txt`: Contains python dependencies for your application - -## Step-2: Test app locally - -You can run the app locally by simply doing: - -```bash Run locally -pip install -r requirements.txt -ec dev -``` - -## Step-3: Deploy to gradio.app - -```bash Deploy to gradio.app -ec deploy -``` - -This will run `gradio deploy` which will prompt you questions and deploy your app directly to huggingface spaces. - -gradio app - -## Seeking help? - -If you run into issues with deployment, please feel free to reach out to us via any of the following methods: - - diff --git a/embedchain/docs/deployment/huggingface_spaces.mdx b/embedchain/docs/deployment/huggingface_spaces.mdx deleted file mode 100644 index 5b8811e41..000000000 --- a/embedchain/docs/deployment/huggingface_spaces.mdx +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: 'Huggingface.co' -description: 'Deploy your RAG application to huggingface.co platform' ---- - -With Embedchain, you can directly host your apps in just three steps to huggingface spaces where you can view and deploy your app to the world. - -We support two types of deployment to huggingface spaces: - - - - Streamlit.io - - - Gradio.app - - - -## Using streamlit.io - -### Step 1: Create a new RAG app - -Create a new RAG app using the following command: - -```bash -mkdir my-rag-app -ec create --template=hf/streamlit.io # inside my-rag-app directory -``` - -When you run this for the first time, you'll be asked to login to huggingface.co. Once you login, you'll need to create a **write** token. You can create a write token by going to [huggingface.co settings](https://huggingface.co/settings/token). Once you create a token, you'll be asked to enter the token in the terminal. - -This will also create an `embedchain.json` file in your app directory. Add a `name` key into the `embedchain.json` file. This will be the "repo-name" of your app in huggingface spaces. - -```json embedchain.json -{ - "name": "my-rag-app", - "provider": "hf/streamlit.io" -} -``` - -### Step-2: Test app locally - -You can run the app locally by simply doing: - -```bash Run locally -pip install -r requirements.txt -ec dev -``` - -### Step-3: Deploy to huggingface spaces - -```bash Deploy to huggingface spaces -ec deploy -``` - -This will deploy your app to huggingface spaces. You can view your app at `https://huggingface.co/spaces//my-rag-app`. This will get prompted in the terminal once the app is deployed. - -## Using gradio.app - -Similar to streamlit.io, you can deploy your app to gradio.app in just three steps. - -### Step 1: Create a new RAG app - -Create a new RAG app using the following command: - -```bash -mkdir my-rag-app -ec create --template=hf/gradio.app # inside my-rag-app directory -``` - -When you run this for the first time, you'll be asked to login to huggingface.co. Once you login, you'll need to create a **write** token. You can create a write token by going to [huggingface.co settings](https://huggingface.co/settings/token). Once you create a token, you'll be asked to enter the token in the terminal. - -This will also create an `embedchain.json` file in your app directory. Add a `name` key into the `embedchain.json` file. This will be the "repo-name" of your app in huggingface spaces. - -```json embedchain.json -{ - "name": "my-rag-app", - "provider": "hf/gradio.app" -} -``` - -### Step-2: Test app locally - -You can run the app locally by simply doing: - -```bash Run locally -pip install -r requirements.txt -ec dev -``` - -### Step-3: Deploy to huggingface spaces - -```bash Deploy to huggingface spaces -ec deploy -``` - -This will deploy your app to huggingface spaces. You can view your app at `https://huggingface.co/spaces//my-rag-app`. This will get prompted in the terminal once the app is deployed. - -## Seeking help? - -If you run into issues with deployment, please feel free to reach out to us via any of the following methods: - - diff --git a/embedchain/docs/deployment/modal_com.mdx b/embedchain/docs/deployment/modal_com.mdx deleted file mode 100644 index e82d367b6..000000000 --- a/embedchain/docs/deployment/modal_com.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: 'Modal.com' -description: 'Deploy your RAG application to modal.com platform' ---- - -Embedchain has a nice and simple abstraction on top of the [Modal.com](https://modal.com/) tools to let developers deploy RAG application to modal.com platform seamlessly. - -Follow the instructions given below to deploy your first application quickly: - - -## Step-1 Create RAG application: - -We provide a command line utility called `ec` in embedchain that inherits the template for `modal.com` platform and help you deploy the app. Follow the instructions to create a modal.com app using the template provided: - - -```bash Create application -pip install embedchain[modal] -mkdir my-rag-app -ec create --template=modal.com -``` - -This `create` command will open a browser window and ask you to login to your modal.com account and will generate a directory structure like this: - -```bash -├── app.py -├── .env -├── .env.example -├── embedchain.json -└── requirements.txt -``` - -Feel free to edit the files as required. -- `app.py`: Contains API app code -- `.env`: Contains environment variables for production -- `.env.example`: Contains dummy environment variables (can ignore this file) -- `embedchain.json`: Contains embedchain specific configuration for deployment (you don't need to configure this) -- `requirements.txt`: Contains python dependencies for your FastAPI application - -## Step-2: Test app locally - -You can run the app locally by simply doing: - -```bash Run locally -pip install -r requirements.txt -ec dev -``` - -## Step-3: Deploy to modal.com - -You can deploy to modal.com using the following command: -```bash Deploy app -ec deploy -``` - -Once this step finished, it will provide you with the deployment endpoint where you can access the app live. It will look something like this (Swagger docs): - - - -## Seeking help? - -If you run into issues with deployment, please feel free to reach out to us via any of the following methods: - - diff --git a/embedchain/docs/deployment/railway.mdx b/embedchain/docs/deployment/railway.mdx deleted file mode 100644 index ef8a60ab8..000000000 --- a/embedchain/docs/deployment/railway.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: 'Railway.app' -description: 'Deploy your RAG application to railway.app' ---- - -It's easy to host your Embedchain-powered apps and APIs on railway. - -Follow the instructions given below to deploy your first application quickly: - -## Step-1: Create RAG app - -```bash Install embedchain -pip install embedchain -``` - - -**Create a full stack app using Embedchain CLI** - -To use your hosted embedchain RAG app, you can easily set up a FastAPI server that can be used anywhere. -To easily set up a FastAPI server, check out [Get started with Full stack](https://docs.embedchain.ai/get-started/full-stack) page. - -Hosting this server on railway is super easy! - - - -## Step-2: Set up your project - -### With Docker - -You can create a `Dockerfile` in the root of the project, with all the instructions. However, this method is sometimes slower in deployment. - -### Without Docker - -By default, Railway uses Python 3.7. Embedchain requires the python version to be >3.9 in order to install. - -To fix this, create a `.python-version` file in the root directory of your project and specify the correct version - -```bash .python-version -3.10 -``` - -You also need to create a `requirements.txt` file to specify the requirements. - -```bash requirements.txt -python-dotenv -embedchain -fastapi==0.108.0 -uvicorn==0.25.0 -embedchain -beautifulsoup4 -sentence-transformers -``` - -## Step-3: Deploy to Railway 🚀 - -1. Go to https://railway.app and create an account. -2. Create a project by clicking on the "Start a new project" button - -### With Github - -Select `Empty Project` or `Deploy from Github Repo`. - -You should be all set! - -### Without Github - -You can also use the railway CLI to deploy your apps from the terminal, if you don't want to connect a git repository. - -To do this, just run this command in your terminal - -```bash Install and set up railway CLI -npm i -g @railway/cli -railway login -railway link [projectID] -``` - -Finally, run `railway up` to deploy your app. -```bash Deploy -railway up -``` - -## Seeking help? - -If you run into issues with deployment, please feel free to reach out to us via any of the following methods: - - diff --git a/embedchain/docs/deployment/render_com.mdx b/embedchain/docs/deployment/render_com.mdx deleted file mode 100644 index 81ba7f6df..000000000 --- a/embedchain/docs/deployment/render_com.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: 'Render.com' -description: 'Deploy your RAG application to render.com platform' ---- - -Embedchain has a nice and simple abstraction on top of the [render.com](https://render.com/) tools to let developers deploy RAG application to render.com platform seamlessly. - -Follow the instructions given below to deploy your first application quickly: - -## Step-1: Install `render` command line - - -```bash OSX -brew tap render-oss/render -brew install render -``` - -```bash Linux -# Make sure you have deno installed -> https://docs.render.com/docs/cli#from-source-unsupported-operating-systems -git clone https://github.com/render-oss/render-cli -cd render-cli -make deps -deno task run -deno compile -``` - -```bash Windows -choco install rendercli -``` - - -In case you run into issues, refer to official [render.com docs](https://docs.render.com/docs/cli). - -## Step-2 Create RAG application: - -We provide a command line utility called `ec` in embedchain that inherits the template for `render.com` platform and help you deploy the app. Follow the instructions to create a render.com app using the template provided: - - -```bash Create application -pip install embedchain -mkdir my-rag-app -ec create --template=render.com -``` - -This `create` command will open a browser window and ask you to login to your render.com account and will generate a directory structure like this: - -```bash -├── app.py -├── .env -├── render.yaml -├── embedchain.json -└── requirements.txt -``` - -Feel free to edit the files as required. -- `app.py`: Contains API app code -- `.env`: Contains environment variables for production -- `render.yaml`: Contains render.com specific configuration for deployment (configure this according to your needs, follow [this](https://docs.render.com/docs/blueprint-spec) for more info) -- `embedchain.json`: Contains embedchain specific configuration for deployment (you don't need to configure this) -- `requirements.txt`: Contains python dependencies for your application - -## Step-3: Test app locally - -You can run the app locally by simply doing: - -```bash Run locally -pip install -r requirements.txt -ec dev -``` - -## Step-4: Deploy to render.com - -Before deploying to render.com, you only have to set up one thing. - -In the render.yaml file, make sure to modify the repo key by inserting the URL of your Git repository where your application will be hosted. You can create a repository from [GitHub](https://github.com) or [GitLab](https://gitlab.com/users/sign_in). - -After that, you're ready to deploy on render.com. - -```bash Deploy app -ec deploy -``` - -When you run this, it should open up your render dashboard and you can see the app being deployed. You can find your hosted link over there only. - -You can also check the logs, monitor app status etc on their dashboard by running command `render dashboard`. - - - -## Seeking help? - -If you run into issues with deployment, please feel free to reach out to us via any of the following methods: - - diff --git a/embedchain/docs/deployment/streamlit_io.mdx b/embedchain/docs/deployment/streamlit_io.mdx deleted file mode 100644 index 93dde7400..000000000 --- a/embedchain/docs/deployment/streamlit_io.mdx +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: 'Streamlit.io' -description: 'Deploy your RAG application to streamlit.io platform' ---- - -Embedchain offers a Streamlit template to facilitate the development of RAG chatbot applications in just three easy steps. - -Follow the instructions given below to deploy your first application quickly: - -## Step-1: Create RAG app - -We provide a command line utility called `ec` in embedchain that inherits the template for `streamlit.io` platform and help you deploy the app. Follow the instructions to create a streamlit.io app using the template provided: - -```bash Install embedchain -pip install embedchain -``` - -```bash Create application -mkdir my-rag-app -ec create --template=streamlit.io -``` - -This will generate a directory structure like this: - -```bash -├── .streamlit -│ └── secrets.toml -├── app.py -├── embedchain.json -└── requirements.txt -``` - -Feel free to edit the files as required. -- `app.py`: Contains API app code -- `.streamlit/secrets.toml`: Contains secrets for your application -- `embedchain.json`: Contains embedchain specific configuration for deployment (you don't need to configure this) -- `requirements.txt`: Contains python dependencies for your application - -Add your `OPENAI_API_KEY` in `.streamlit/secrets.toml` file to run and deploy the app. - -## Step-2: Test app locally - -You can run the app locally by simply doing: - -```bash Run locally -pip install -r requirements.txt -ec dev -``` - -## Step-3: Deploy to streamlit.io - -![Streamlit App deploy button](https://github.com/embedchain/embedchain/assets/73601258/90658e28-29e5-4ceb-9659-37ff8b861a29) - -Use the deploy button from the streamlit website to deploy your app. - -You can refer this [guide](https://docs.streamlit.io/streamlit-community-cloud/deploy-your-app) if you run into any problems. - -## Seeking help? - -If you run into issues with deployment, please feel free to reach out to us via any of the following methods: - - diff --git a/embedchain/docs/development.mdx b/embedchain/docs/development.mdx deleted file mode 100644 index 878300893..000000000 --- a/embedchain/docs/development.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: 'Development' -description: 'Learn how to preview changes locally' ---- - - - **Prerequisite** You should have installed Node.js (version 18.10.0 or - higher). - - -Step 1. Install Mintlify on your OS: - - - -```bash npm -npm i -g mintlify -``` - -```bash yarn -yarn global add mintlify -``` - - - -Step 2. Go to the docs are located (where you can find `mint.json`) and run the following command: - -```bash -mintlify dev -``` - -The documentation website is now available at `http://localhost:3000`. - -### Custom Ports - -Mintlify uses port 3000 by default. You can use the `--port` flag to customize the port Mintlify runs on. For example, use this command to run in port 3333: - -```bash -mintlify dev --port 3333 -``` - -You will see an error like this if you try to run Mintlify in a port that's already taken: - -```md -Error: listen EADDRINUSE: address already in use :::3000 -``` - -## Mintlify Versions - -Each CLI is linked to a specific version of Mintlify. Please update the CLI if your local website looks different than production. - - - -```bash npm -npm i -g mintlify@latest -``` - -```bash yarn -yarn global upgrade mintlify -``` - - - -## Deployment - - - Unlimited editors available under the [Startup - Plan](https://mintlify.com/pricing) - - -You should see the following if the deploy successfully went through: - - - - - -## Troubleshooting - -Here's how to solve some common problems when working with the CLI. - - - - Update to Node v18. Run `mintlify install` and try again. - - -Go to the `C:/Users/Username/.mintlify/` directory and remove the `mint` -folder. Then Open the Git Bash in this location and run `git clone -https://github.com/mintlify/mint.git`. - -Repeat step 3. - - - - Try navigating to the root of your device and delete the ~/.mintlify folder. - Then run `mintlify dev` again. - - - -Curious about what changed in a CLI version? [Check out the CLI changelog.](/changelog/command-line) diff --git a/embedchain/docs/examples/chat-with-PDF.mdx b/embedchain/docs/examples/chat-with-PDF.mdx deleted file mode 100644 index ad8fb9a5b..000000000 --- a/embedchain/docs/examples/chat-with-PDF.mdx +++ /dev/null @@ -1,32 +0,0 @@ -### Embedchain Chat with PDF App - -You can easily create and deploy your own `chat-pdf` App using Embedchain. - -Here are few simple steps for you to create and deploy your app: - -1. Fork the embedchain repo from [Github](https://github.com/embedchain/embedchain). - - -If you run into problems with forking, please refer to [github docs](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) for forking a repo. - - -2. Navigate to `chat-pdf` example app from your forked repo: - -```bash -cd /examples/chat-pdf -``` - -3. Run your app in development environment with simple commands - -```bash -pip install -r requirements.txt -ec dev -``` - -Feel free to improve our simple `chat-pdf` streamlit app and create pull request to showcase your app [here](https://docs.embedchain.ai/examples/showcase) - -4. You can easily deploy your app using Streamlit interface - -Connect your Github account with Streamlit and refer this [guide](https://docs.streamlit.io/streamlit-community-cloud/deploy-your-app) to deploy your app. - -You can also use the deploy button from your streamlit website you see when running `ec dev` command. diff --git a/embedchain/docs/examples/community/showcase.mdx b/embedchain/docs/examples/community/showcase.mdx deleted file mode 100644 index d8b511919..000000000 --- a/embedchain/docs/examples/community/showcase.mdx +++ /dev/null @@ -1,115 +0,0 @@ ---- -title: '🎪 Community showcase' ---- - -Embedchain community has been super active in creating demos on top of Embedchain. On this page, we showcase all the apps, blogs, videos, and tutorials created by the community. ❤️ - -## Apps - -### Open Source - -- [My GSoC23 bot- Streamlit chat](https://github.com/lucifertrj/EmbedChain_GSoC23_BOT) by Tarun Jain -- [Discord Bot for LLM chat](https://github.com/Reidond/discord_bots_playground/tree/c8b0c36541e4b393782ee506804c4b6962426dd6/python/chat-channel-bot) by Reidond -- [EmbedChain-Streamlit-Docker App](https://github.com/amjadraza/embedchain-streamlit-app) by amjadraza -- [Harry Potter Philosphers Stone Bot](https://github.com/vinayak-kempawad/Harry_Potter_Philosphers_Stone_Bot/) by Vinayak Kempawad, ([LinkedIn post](https://www.linkedin.com/feed/update/urn:li:activity:7080907532155686912/)) -- [LLM bot trained on own messages](https://github.com/Harin329/harinBot) by Hao Wu - -### Closed Source - -- [Taobot.io](https://taobot.io) - chatbot & knowledgebase hybrid by [cachho](https://github.com/cachho) -- [Create Instant ChatBot 🤖 using embedchain](https://databutton.com/v/h3e680h9) by Avra, ([Tweet](https://twitter.com/Avra_b/status/1674704745154641920/)) -- [JOBO 🤖 — The AI-driven sidekick to craft your resume](https://try-jobo.com/) by Enrico Willemse, ([LinkedIn Post](https://www.linkedin.com/posts/enrico-willemse_jobai-gptfun-embedchain-activity-7090340080879374336-ueLB/)) -- [Explore Your Knowledge Base: Interactive chats over various forms of documents](https://chatdocs.dkedar.com/) by Kedar Dabhadkar, ([LinkedIn Post](https://www.linkedin.com/posts/dkedar7_machinelearning-llmops-activity-7092524836639424513-2O3L/)) -- [Chatbot trained on 1000+ videos of Ester hicks the co-author behind the famous book Secret](https://ask-abraham.thoughtseed.repl.co) by Mohan Kumar - - -## Templates - -### Replit -- [Embedchain Chat Bot](https://replit.com/@taranjeet1/Embedchain-Chat-Bot) by taranjeetio -- [Embedchain Memory Chat Bot Template](https://replit.com/@taranjeetio/Embedchain-Memory-Chat-Bot-Template) by taranjeetio -- [Chatbot app to demonstrate question-answering using retrieved information](https://replit.com/@AllisonMorrell/EmbedChainlitPublic) by Allison Morrell, ([LinkedIn Post](https://www.linkedin.com/posts/allison-morrell-2889275a_retrievalbot-screenshots-activity-7080339991754649600-wihZ/)) - -## Posts - -### Blogs - -- [Customer Service LINE Bot](https://www.evanlin.com/langchain-embedchain/) by Evan Lin -- [Chatbot in Under 5 mins using Embedchain](https://medium.com/@ayush.wattal/chatbot-in-under-5-mins-using-embedchain-a4f161fcf9c5) by Ayush Wattal -- [Understanding what the LLM framework embedchain does](https://zenn.dev/hijikix/articles/4bc8d60156a436) by Daisuke Hashimoto -- [In bed with GPT and Node.js](https://dev.to/worldlinetech/in-bed-with-gpt-and-nodejs-4kh2) by Raphaël Semeteys, ([LinkedIn Post](https://www.linkedin.com/posts/raphaelsemeteys_in-bed-with-gpt-and-nodejs-activity-7088113552326029313-nn87/)) -- [Using Embedchain — A powerful LangChain Python wrapper to build Chat Bots even faster!⚡](https://medium.com/@avra42/using-embedchain-a-powerful-langchain-python-wrapper-to-build-chat-bots-even-faster-35c12994a360) by Avra, ([Tweet](https://twitter.com/Avra_b/status/1686767751560310784/)) -- [What is the Embedchain library?](https://jahaniwww.com/%da%a9%d8%aa%d8%a7%d8%a8%d8%ae%d8%a7%d9%86%d9%87-embedchain/) by Ali Jahani, ([LinkedIn Post](https://www.linkedin.com/posts/ajahani_aepaetaeqaexaggahyaeu-aetaexaesabraeaaeqaepaeu-activity-7097605202135904256-ppU-/)) -- [LangChain is Nice, But Have You Tried EmbedChain ?](https://medium.com/thoughts-on-machine-learning/langchain-is-nice-but-have-you-tried-embedchain-215a34421cde) by FS Ndzomga, ([Tweet](https://twitter.com/ndzfs/status/1695583640372035951/)) -- [Simplest Method to Build a Custom Chatbot with GPT-3.5 (via Embedchain)](https://www.ainewsletter.today/p/simplest-method-to-build-a-custom) by Arjun, ([Tweet](https://twitter.com/aiguy_arjun/status/1696393808467091758/)) - -### LinkedIn - -- [What is embedchain](https://www.linkedin.com/posts/activity-7079393104423698432-wRyi/) by Rithesh Sreenivasan -- [Building a chatbot with EmbedChain](https://www.linkedin.com/posts/activity-7078434598984060928-Zdso/) by Lior Sinclair -- [Making chatbot without vs with embedchain](https://www.linkedin.com/posts/kalyanksnlp_llms-chatbots-langchain-activity-7077453416221863936-7N1L/) by Kalyan KS -- [EmbedChain - very intuitive, first you index your data and then query!](https://www.linkedin.com/posts/shubhamsaboo_embedchain-a-framework-to-easily-create-activity-7079535460699557888-ad1X/) by Shubham Saboo -- [EmbedChain - Harnessing power of LLM](https://www.linkedin.com/posts/uditsaini_chatbotrevolution-llmpoweredbots-embedchainframework-activity-7077520356827181056-FjTK/) by Udit S. -- [AI assistant for ABBYY Vantage](https://www.linkedin.com/posts/maximevermeir_llm-github-abbyy-activity-7081658972071424000-fXfZ/) by Maxime V. -- [About embedchain](https://www.linkedin.com/feed/update/urn:li:activity:7080984218914189312/) by Morris Lee -- [How to use Embedchain](https://www.linkedin.com/posts/nehaabansal_github-embedchainembedchain-framework-activity-7085830340136595456-kbW5/) by Neha Bansal -- [Youtube/Webpage summary for Energy Study](https://www.linkedin.com/posts/bar%C4%B1%C5%9F-sanl%C4%B1-34b82715_enerji-python-activity-7082735341563977730-Js0U/) by Barış Sanlı, ([Tweet](https://twitter.com/barissanli/status/1676968784979193857/)) -- [Demo: How to use Embedchain? (Contains Collab Notebook link)](https://www.linkedin.com/posts/liorsinclair_embedchain-is-getting-a-lot-of-traction-because-activity-7103044695995424768-RckT/) by Lior Sinclair - -### Twitter - -- [What is embedchain](https://twitter.com/AlphaSignalAI/status/1672668574450847745) by Lior -- [Building a chatbot with Embedchain](https://twitter.com/Saboo_Shubham_/status/1673537044419686401) by Shubham Saboo -- [Chatbot docker image behind an API with yaml configs with Embedchain](https://twitter.com/tricalt/status/1678411430192730113/) by Vasilije -- [Build AI powered PDF chatbot with just five lines of Python code with Embedchain!](https://twitter.com/Saboo_Shubham_/status/1676627104866156544/) by Shubham Saboo -- [Chatbot against a youtube video using embedchain](https://twitter.com/smaameri/status/1675201443043704834/) by Sami Maameri -- [Highlights of EmbedChain](https://twitter.com/carl_AIwarts/status/1673542204328120321/) by carl_AIwarts -- [Build Llama-2 chatbot in less than 5 minutes](https://twitter.com/Saboo_Shubham_/status/1682168956918833152/) by Shubham Saboo -- [All cool features of embedchain](https://twitter.com/DhravyaShah/status/1683497882438217728/) by Dhravya Shah, ([LinkedIn Post](https://www.linkedin.com/posts/dhravyashah_what-if-i-tell-you-that-you-can-make-an-ai-activity-7089459599287726080-ZIYm/)) -- [Read paid Medium articles for Free using embedchain](https://twitter.com/kumarkaushal_/status/1688952961622585344) by Kaushal Kumar - -## Videos - -- [Embedchain in one shot](https://www.youtube.com/watch?v=vIhDh7H73Ww&t=82s) by AI with Tarun -- [embedChain Create LLM powered bots over any dataset Python Demo Tesla Neurallink Chatbot Example](https://www.youtube.com/watch?v=bJqAn22a6Gc) by Rithesh Sreenivasan -- [Embedchain - NEW 🔥 Langchain BABY to build LLM Bots](https://www.youtube.com/watch?v=qj_GNQ06I8o) by 1littlecoder -- [EmbedChain -- NEW!: Build LLM-Powered Bots with Any Dataset](https://www.youtube.com/watch?v=XmaBezzGHu4) by DataInsightEdge -- [Chat With Your PDFs in less than 10 lines of code! EMBEDCHAIN tutorial](https://www.youtube.com/watch?v=1ugkcsAcw44) by Phani Reddy -- [How To Create A Custom Knowledge AI Powered Bot | Install + How To Use](https://www.youtube.com/watch?v=VfCrIiAst-c) by The Ai Solopreneur -- [Build Custom Chatbot in 6 min with this Framework [Beginner Friendly]](https://www.youtube.com/watch?v=-8HxOpaFySM) by Maya Akim -- [embedchain-streamlit-app](https://www.youtube.com/watch?v=3-9GVd-3v74) by Amjad Raza -- [🤖CHAT with ANY ONLINE RESOURCES using EMBEDCHAIN - a LangChain wrapper, in few lines of code !](https://www.youtube.com/watch?v=Mp7zJe4TIdM) by Avra -- [Building resource-driven LLM-powered bots with Embedchain](https://www.youtube.com/watch?v=IVfcAgxTO4I) by BugBytes -- [embedchain-streamlit-demo](https://www.youtube.com/watch?v=yJAWB13FhYQ) by Amjad Raza -- [Embedchain - create your own AI chatbots using open source models](https://www.youtube.com/shorts/O3rJWKwSrWE) by Dhravya Shah -- [AI ChatBot in 5 lines Python Code](https://www.youtube.com/watch?v=zjWvLJLksv8) by Data Engineering -- [Interview with Karl Marx](https://www.youtube.com/watch?v=5Y4Tscwj1xk) by Alexander Ray Williams -- [Vlog where we try to build a bot based on our content on the internet](https://www.youtube.com/watch?v=I2w8CWM3bx4) by DV, ([Tweet](https://twitter.com/dvcoolster/status/1688387017544261632)) -- [CHAT with ANY ONLINE RESOURCES using EMBEDCHAIN|STREAMLIT with MEMORY |All OPENSOURCE](https://www.youtube.com/watch?v=TqQIHWoWTDQ&pp=ygUKZW1iZWRjaGFpbg%3D%3D) by DataInsightEdge -- [Build POWERFUL LLM Bots EASILY with Your Own Data - Embedchain - Langchain 2.0? (Tutorial)](https://www.youtube.com/watch?v=jE24Y_GasE8) by WorldofAI, ([Tweet](https://twitter.com/intheworldofai/status/1696229166922780737)) -- [Embedchain: An AI knowledge base assistant for customizing enterprise private data, which can be connected to discord, whatsapp, slack, tele and other terminals (with gradio to build a request interface) in Chinese](https://www.youtube.com/watch?v=5RZzCJRk-d0) by AIGC LINK -- [Embedchain Introduction](https://www.youtube.com/watch?v=Jet9zAqyggI) by Fahd Mirza - -## Mentions - -### Github repos - -- [Awesome-LLM](https://github.com/Hannibal046/Awesome-LLM) -- [awesome-chatgpt-api](https://github.com/reorx/awesome-chatgpt-api) -- [awesome-langchain](https://github.com/kyrolabs/awesome-langchain) -- [Awesome-Prompt-Engineering](https://github.com/promptslab/Awesome-Prompt-Engineering) -- [awesome-chatgpt](https://github.com/eon01/awesome-chatgpt) -- [Awesome-LLMOps](https://github.com/tensorchord/Awesome-LLMOps) -- [awesome-generative-ai](https://github.com/filipecalegario/awesome-generative-ai) -- [awesome-gpt](https://github.com/formulahendry/awesome-gpt) -- [awesome-ChatGPT-repositories](https://github.com/taishi-i/awesome-ChatGPT-repositories) -- [awesome-gpt-prompt-engineering](https://github.com/snwfdhmp/awesome-gpt-prompt-engineering) -- [awesome-chatgpt](https://github.com/awesome-chatgpt/awesome-chatgpt) -- [awesome-llm-and-aigc](https://github.com/sjinzh/awesome-llm-and-aigc) -- [awesome-compbio-chatgpt](https://github.com/csbl-br/awesome-compbio-chatgpt) -- [Awesome-LLM4Tool](https://github.com/OpenGVLab/Awesome-LLM4Tool) - -## Meetups - -- [Dash and ChatGPT: Future of AI-enabled apps 30/08/23](https://go.plotly.com/dash-chatgpt) -- [Pie & AI: Bangalore - Build end-to-end LLM app using Embedchain 01/09/23](https://www.eventbrite.com/e/pie-ai-bangalore-build-end-to-end-llm-app-using-embedchain-tickets-698045722547) diff --git a/embedchain/docs/examples/discord_bot.mdx b/embedchain/docs/examples/discord_bot.mdx deleted file mode 100644 index 247f3c634..000000000 --- a/embedchain/docs/examples/discord_bot.mdx +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: "🤖 Discord Bot" ---- - -### 🔑 Keys Setup - -- Set your `OPENAI_API_KEY` in your variables.env file. -- Go to [https://discord.com/developers/applications/](https://discord.com/developers/applications/) and click on `New Application`. -- Enter the name for your bot, accept the terms and click on `Create`. On the resulting page, enter the details of your bot as you like. -- On the left sidebar, click on `Bot`. Under the heading `Privileged Gateway Intents`, toggle all 3 options to ON position. Save your changes. -- Now click on `Reset Token` and copy the token value. Set it as `DISCORD_BOT_TOKEN` in .env file. -- On the left sidebar, click on `OAuth2` and go to `General`. -- Set `Authorization Method` to `In-app Authorization`. Under `Scopes` select `bot`. -- Under `Bot Permissions` allow the following and then click on `Save Changes`. - -```text -Send Messages (under Text Permissions) -``` - -- Now under `OAuth2` and go to `URL Generator`. Under `Scopes` select `bot`. -- Under `Bot Permissions` set the same permissions as above. -- Now scroll down and copy the `Generated URL`. Paste it in a browser window and select the Server where you want to add the bot. -- Click on `Continue` and authorize the bot. -- 🎉 The bot has been successfully added to your server. But it's still offline. - -### Take the bot online - - - - ```bash - docker run --name discord-bot -e OPENAI_API_KEY=sk-xxx -e DISCORD_BOT_TOKEN=xxx -p 8080:8080 embedchain/discord-bot:latest - ``` - - - ```bash - pip install --upgrade "embedchain[discord]" - - python -m embedchain.bots.discord - - # or if you prefer to see the question and not only the answer, run it with - python -m embedchain.bots.discord --include-question - ``` - - - -### 🚀 Usage Instructions - -- Go to the server where you have added your bot. - ![Slash commands interaction with bot](https://github.com/embedchain/embedchain/assets/73601258/bf1414e3-d408-4863-b0d2-ef382a76467e) -- You can add data sources to the bot using the slash command: - -```text -/ec add -``` - -- You can ask your queries from the bot using the slash command: - -```text -/ec query -``` - -- You can chat with the bot using the slash command: - -```text -/ec chat -``` - -📝 Note: To use the bot privately, you can message the bot directly by right clicking the bot and selecting `Message`. - -🎉 Happy Chatting! 🎉 diff --git a/embedchain/docs/examples/nextjs-assistant.mdx b/embedchain/docs/examples/nextjs-assistant.mdx deleted file mode 100644 index 86f82fb4f..000000000 --- a/embedchain/docs/examples/nextjs-assistant.mdx +++ /dev/null @@ -1,124 +0,0 @@ -Fork the Embedchain repo on [Github](https://github.com/embedchain/embedchain) to create your own NextJS discord and slack bot powered by Embedchain. - -If you run into problems with forking, please refer to [github docs](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) for forking a repo. - -We will work from the `examples/nextjs` folder so change your current working directory by running the command - `cd /examples/nextjs` - -# Installation - -First, lets start by install all the required packages and dependencies. - -- Install all the required python packages by running ```pip install -r requirements.txt``` - -- We will use [Fly.io](https://fly.io/) to deploy our embedchain app, discord and slack bot. Follow the step one to install [Fly.io CLI](https://docs.embedchain.ai/deployment/fly_io#step-1-install-flyctl-command-line) - -# Developement - -## Embedchain App - -First, we need an Embedchain app powered with the knowledge of NextJS. We have already created an embedchain app using FastAPI in `ec_app` folder for you. Feel free to ingest data of your choice to power the App. - - -Navigate to `ec_app` folder and create `.env` file in this folder and set your OpenAI API key as shown in `.env.example` file. If you want to use other open-source models, feel free to use the app config in `app.py`. More details for using custom configuration for Embedchain app is [available here](https://docs.embedchain.ai/api-reference/advanced/configuration). - - -Before running the ec commands to develope the app, open `fly.toml` file and update the `name` variable to something unique. This is important as `fly.io` requires users to provide a globally unique deployment app names. - -Now, we need to launch this application with fly.io. You can see your app on [fly.io dashboard](https://fly.io/dashboard). Run the following command to launch your app on fly.io: -```bash -fly launch --no-deploy -``` - -To run the app in development, run the following command: - -```bash -ec dev -``` - -Run `ec deploy` to deploy your app on Fly.io. Once you deploy your app, save the endpoint on which our discord and slack bot will send requests. - - -## Discord bot - -For discord bot, you will need to create the bot on discord developer portal and get the discord bot token and your discord bot name. - -While keeping in mind the following note, create the discord bot by following the instructions from our [discord bot docs](https://docs.embedchain.ai/examples/discord_bot) and get discord bot token. - - -You do not need to set `OPENAI_API_KEY` to run this discord bot. Follow the remaining instructions to create a discord bot app. We recommend you to give the following sets of bot permissions to run the discord bot without errors: - -``` -(General Permissions) -Read Message/View Channels - -(Text Permissions) -Send Messages -Create Public Thread -Create Private Thread -Send Messages in Thread -Manage Threads -Embed Links -Read Message History -``` - - -Once you have your discord bot token and discord app name. Navigate to `nextjs_discord` folder and create `.env` file and define your discord bot token, discord bot name and endpoint of your embedchain app as shown in `.env.example` file. - -To run the app in development: - -```bash -python app.py -``` - -Before deploying the app, open `fly.toml` file and update the `name` variable to something unique. This is important as `fly.io` requires users to provide a globally unique deployment app names. - -Now, we need to launch this application with fly.io. You can see your app on [fly.io dashboard](https://fly.io/dashboard). Run the following command to launch your app on fly.io: -```bash -fly launch --no-deploy -``` - -Run `ec deploy` to deploy your app on Fly.io. Once you deploy your app, your discord bot will be live! - - -## Slack bot - -For Slack bot, you will need to create the bot on slack developer portal and get the slack bot token and slack app token. - -### Setup - -- Create a workspace on Slack if you don't have one already by clicking [here](https://slack.com/intl/en-in/). -- Create a new App on your Slack account by going [here](https://api.slack.com/apps). -- Select `From Scratch`, then enter the Bot Name and select your workspace. -- Go to `App Credentials` section on the `Basic Information` tab from the left sidebar, create your app token and save it in your `.env` file as `SLACK_APP_TOKEN`. -- Go to `Socket Mode` tab from the left sidebar and enable the socket mode to listen to slack message from your workspace. -- (Optional) Under the `App Home` tab you can change your App display name and default name. -- Navigate to `Event Subscription` tab, and enable the event subscription so that we can listen to slack events. -- Once you enable the event subscription, you will need to subscribe to bot events to authorize the bot to listen to app mention events of the bot. Do that by tapping on `Add Bot User Event` button and select `app_mention`. -- On the left Sidebar, go to `OAuth and Permissions` and add the following scopes under `Bot Token Scopes`: -```text -app_mentions:read -channels:history -channels:read -chat:write -emoji:read -reactions:write -reactions:read -``` -- Now select the option `Install to Workspace` and after it's done, copy the `Bot User OAuth Token` and set it in your `.env` file as `SLACK_BOT_TOKEN`. - -Once you have your slack bot token and slack app token. Navigate to `nextjs_slack` folder and create `.env` file and define your slack bot token, slack app token and endpoint of your embedchain app as shown in `.env.example` file. - -To run the app in development: - -```bash -python app.py -``` - -Before deploying the app, open `fly.toml` file and update the `name` variable to something unique. This is important as `fly.io` requires users to provide a globally unique deployment app names. - -Now, we need to launch this application with fly.io. You can see your app on [fly.io dashboard](https://fly.io/dashboard). Run the following command to launch your app on fly.io: -```bash -fly launch --no-deploy -``` - -Run `ec deploy` to deploy your app on Fly.io. Once you deploy your app, your slack bot will be live! diff --git a/embedchain/docs/examples/notebooks-and-replits.mdx b/embedchain/docs/examples/notebooks-and-replits.mdx deleted file mode 100644 index 2da7208a4..000000000 --- a/embedchain/docs/examples/notebooks-and-replits.mdx +++ /dev/null @@ -1,138 +0,0 @@ ---- -title: Notebooks & Replits ---- - -# Explore awesome apps - -Check out the remarkable work accomplished using [Embedchain](https://app.embedchain.ai/custom-gpts/). - -## Collection of Google colab notebook and Replit links for users - -Get started with Embedchain by trying out the examples below. You can run the examples in your browser using Google Colab or Replit. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LLMGoogle ColabReplit
OpenAIOpen In ColabTry with Replit Badge
AnthropicOpen In ColabTry with Replit Badge
Azure OpenAIOpen In ColabTry with Replit Badge
VertexAIOpen In ColabTry with Replit Badge
CohereOpen In ColabTry with Replit Badge
TogetherOpen In Colab
OllamaOpen In Colab
Hugging FaceOpen In ColabTry with Replit Badge
JinaChatOpen In ColabTry with Replit Badge
GPT4AllOpen In ColabTry with Replit Badge
Llama2Open In ColabTry with Replit Badge
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Embedding modelGoogle ColabReplit
OpenAIOpen In ColabTry with Replit Badge
VertexAIOpen In ColabTry with Replit Badge
GPT4AllOpen In ColabTry with Replit Badge
Hugging FaceOpen In ColabTry with Replit Badge
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Vector DBGoogle ColabReplit
ChromaDBOpen In ColabTry with Replit Badge
ElasticsearchOpen In ColabTry with Replit Badge
OpensearchOpen In ColabTry with Replit Badge
PineconeOpen In ColabTry with Replit Badge
\ No newline at end of file diff --git a/embedchain/docs/examples/openai-assistant.mdx b/embedchain/docs/examples/openai-assistant.mdx deleted file mode 100644 index ffd312fa7..000000000 --- a/embedchain/docs/examples/openai-assistant.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: 'OpenAI Assistant' ---- - -OpenAI Logo - -Embedchain now supports [OpenAI Assistants API](https://platform.openai.com/docs/assistants/overview) which allows you to build AI assistants within your own applications. An Assistant has instructions and can leverage models, tools, and knowledge to respond to user queries. - -At a high level, an integration of the Assistants API has the following flow: - -1. Create an Assistant in the API by defining custom instructions and picking a model -2. Create a Thread when a user starts a conversation -3. Add Messages to the Thread as the user ask questions -4. Run the Assistant on the Thread to trigger responses. This automatically calls the relevant tools. - -Creating an OpenAI Assistant using Embedchain is very simple 3 step process. - -## Step 1: Create OpenAI Assistant - -Make sure that you have `OPENAI_API_KEY` set in the environment variable. - -```python Initialize -from embedchain.store.assistants import OpenAIAssistant - -assistant = OpenAIAssistant( - name="OpenAI DevDay Assistant", - instructions="You are an organizer of OpenAI DevDay", -) -``` - -If you want to use the existing assistant, you can do something like this: - -```python Initialize -# Load an assistant and create a new thread -assistant = OpenAIAssistant(assistant_id="asst_xxx") - -# Load a specific thread for an assistant -assistant = OpenAIAssistant(assistant_id="asst_xxx", thread_id="thread_xxx") -``` - -## Step-2: Add data to thread - -You can add any custom data source that is supported by Embedchain. Else, you can directly pass the file path on your local system and Embedchain propagates it to OpenAI Assistant. -```python Add data -assistant.add("/path/to/file.pdf") -assistant.add("https://www.youtube.com/watch?v=U9mJuUkhUzk") -assistant.add("https://openai.com/blog/new-models-and-developer-products-announced-at-devday") -``` - -## Step-3: Chat with your Assistant -```python Chat -assistant.chat("How much OpenAI credits were offered to attendees during OpenAI DevDay?") -# Response: 'Every attendee of OpenAI DevDay 2023 was offered $500 in OpenAI credits.' -``` - -You can try it out yourself using the following Google Colab notebook: - - - Open in Colab - diff --git a/embedchain/docs/examples/opensource-assistant.mdx b/embedchain/docs/examples/opensource-assistant.mdx deleted file mode 100644 index f4dcaa521..000000000 --- a/embedchain/docs/examples/opensource-assistant.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: 'Open-Source AI Assistant' ---- - -Embedchain also provides support for creating Open-Source AI Assistants (similar to [OpenAI Assistants API](https://platform.openai.com/docs/assistants/overview)) which allows you to build AI assistants within your own applications using any LLM (OpenAI or otherwise). An Assistant has instructions and can leverage models, tools, and knowledge to respond to user queries. - -At a high level, the Open-Source AI Assistants API has the following flow: - -1. Create an AI Assistant by picking a model -2. Create a Thread when a user starts a conversation -3. Add Messages to the Thread as the user ask questions -4. Run the Assistant on the Thread to trigger responses. This automatically calls the relevant tools. - -Creating an Open-Source AI Assistant is a simple 3 step process. - -## Step 1: Instantiate AI Assistant - -```python Initialize -from embedchain.store.assistants import AIAssistant - -assistant = AIAssistant( - name="My Assistant", - data_sources=[{"source": "https://www.youtube.com/watch?v=U9mJuUkhUzk"}]) -``` - -If you want to use the existing assistant, you can do something like this: - -```python Initialize -# Load an assistant and create a new thread -assistant = AIAssistant(assistant_id="asst_xxx") - -# Load a specific thread for an assistant -assistant = AIAssistant(assistant_id="asst_xxx", thread_id="thread_xxx") -``` - -## Step-2: Add data to thread - -You can add any custom data source that is supported by Embedchain. Else, you can directly pass the file path on your local system and Embedchain propagates it to OpenAI Assistant. - -```python Add data -assistant.add("/path/to/file.pdf") -assistant.add("https://www.youtube.com/watch?v=U9mJuUkhUzk") -assistant.add("https://openai.com/blog/new-models-and-developer-products-announced-at-devday") -``` - -## Step-3: Chat with your AI Assistant - -```python Chat -assistant.chat("How much OpenAI credits were offered to attendees during OpenAI DevDay?") -# Response: 'Every attendee of OpenAI DevDay 2023 was offered $500 in OpenAI credits.' -``` diff --git a/embedchain/docs/examples/poe_bot.mdx b/embedchain/docs/examples/poe_bot.mdx deleted file mode 100644 index 58e831f22..000000000 --- a/embedchain/docs/examples/poe_bot.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: '🔮 Poe Bot' ---- - -### 🚀 Getting started - -1. Install embedchain python package: - -```bash -pip install fastapi-poe==0.0.16 -``` - -2. Create a free account on [Poe](https://www.poe.com?utm_source=embedchain). -3. Click "Create Bot" button on top left. -4. Give it a handle and an optional description. -5. Select `Use API`. -6. Under `API URL` enter your server or ngrok address. You can use your machine's public IP or DNS. Otherwise, employ a proxy server like [ngrok](https://ngrok.com/) to make your local bot accessible. -7. Copy your api key and paste it in `.env` as `POE_API_KEY`. -8. You will need to set `OPENAI_API_KEY` for generating embeddings and using LLM. Copy your OpenAI API key from [here](https://platform.openai.com/account/api-keys) and paste it in `.env` as `OPENAI_API_KEY`. -9. Now create your bot using the following code snippet. - -```bash -# make sure that you have set OPENAI_API_KEY and POE_API_KEY in .env file -from embedchain.bots import PoeBot - -poe_bot = PoeBot() - -# add as many data sources as you want -poe_bot.add("https://en.wikipedia.org/wiki/Adam_D%27Angelo") -poe_bot.add("https://www.youtube.com/watch?v=pJQVAqmKua8") - -# start the bot -# this start the poe bot server on port 8080 by default -poe_bot.start() -``` - -10. You can paste the above in a file called `your_script.py` and then simply do - -```bash -python your_script.py -``` - -Now your bot will start running at port `8080` by default. - -11. You can refer the [Supported Data formats](https://docs.embedchain.ai/advanced/data_types) section to refer the supported data types in embedchain. - -12. Click `Run check` to make sure your machine can be reached. -13. Make sure your bot is private if that's what you want. -14. Click `Create bot` at the bottom to finally create the bot -15. Now your bot is created. - -### 💬 How to use - -- To ask the bot questions, just type your query in the Poe interface: -```text - -``` - -- If you wish to add more data source to the bot, simply update your script and add as many `.add` as you like. You need to restart the server. diff --git a/embedchain/docs/examples/rest-api/add-data.mdx b/embedchain/docs/examples/rest-api/add-data.mdx deleted file mode 100644 index 05ed37968..000000000 --- a/embedchain/docs/examples/rest-api/add-data.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -openapi: post /{app_id}/add ---- - - - -```bash Request -curl --request POST \ - --url http://localhost:8080/{app_id}/add \ - -d "source=https://www.forbes.com/profile/elon-musk" \ - -d "data_type=web_page" -``` - - - - - -```json Response -{ "response": "fec7fe91e6b2d732938a2ec2e32bfe3f" } -``` - - diff --git a/embedchain/docs/examples/rest-api/chat.mdx b/embedchain/docs/examples/rest-api/chat.mdx deleted file mode 100644 index 2571bf716..000000000 --- a/embedchain/docs/examples/rest-api/chat.mdx +++ /dev/null @@ -1,3 +0,0 @@ ---- -openapi: post /{app_id}/chat ---- \ No newline at end of file diff --git a/embedchain/docs/examples/rest-api/check-status.mdx b/embedchain/docs/examples/rest-api/check-status.mdx deleted file mode 100644 index 0893cba4c..000000000 --- a/embedchain/docs/examples/rest-api/check-status.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -openapi: get /ping ---- - - - -```bash Request - curl --request GET \ - --url http://localhost:8080/ping -``` - - - - - -```json Response -{ "ping": "pong" } -``` - - diff --git a/embedchain/docs/examples/rest-api/create.mdx b/embedchain/docs/examples/rest-api/create.mdx deleted file mode 100644 index 35863cea5..000000000 --- a/embedchain/docs/examples/rest-api/create.mdx +++ /dev/null @@ -1,96 +0,0 @@ ---- -openapi: post /create ---- - - - -```bash Request -curl --request POST \ - --url http://localhost:8080/create?app_id=app1 \ - -F "config=@/path/to/config.yaml" -``` - - - - - -```json Response -{ "response": "App created successfully. App ID: app1" } -``` - - - -By default we will use the opensource **gpt4all** model to get started. You can also specify your own config by uploading a config YAML file. - -For example, create a `config.yaml` file (adjust according to your requirements): - -```yaml -app: - config: - id: "default-app" - -llm: - provider: openai - config: - model: "gpt-4o-mini" - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - prompt: | - Use the following pieces of context to answer the query at the end. - If you don't know the answer, just say that you don't know, don't try to make up an answer. - - $context - - Query: $query - - Helpful Answer: - -vectordb: - provider: chroma - config: - collection_name: "rest-api-app" - dir: db - allow_reset: true - -embedder: - provider: openai - config: - model: "text-embedding-ada-002" -``` - -To learn more about custom configurations, check out the [custom configurations docs](https://docs.embedchain.ai/advanced/configuration). To explore more examples of config yamls for embedchain, visit [embedchain/configs](https://github.com/embedchain/embedchain/tree/main/configs). - -Now, you can upload this config file in the request body. - -For example, - -```bash Request -curl --request POST \ - --url http://localhost:8080/create?app_id=my-app \ - -F "config=@/path/to/config.yaml" -``` - -**Note:** To use custom models, an **API key** might be required. Refer to the table below to determine the necessary API key for your provider. - -| Keys | Providers | -| -------------------------- | ------------------------------ | -| `OPENAI_API_KEY ` | OpenAI, Azure OpenAI, Jina etc | -| `OPENAI_API_TYPE` | Azure OpenAI | -| `OPENAI_API_BASE` | Azure OpenAI | -| `OPENAI_API_VERSION` | Azure OpenAI | -| `COHERE_API_KEY` | Cohere | -| `TOGETHER_API_KEY` | Together | -| `ANTHROPIC_API_KEY` | Anthropic | -| `JINACHAT_API_KEY` | Jina | -| `HUGGINGFACE_ACCESS_TOKEN` | Huggingface | -| `REPLICATE_API_TOKEN` | LLAMA2 | - -To add env variables, you can simply run the docker command with the `-e` flag. - -For example, - -```bash -docker run --name embedchain -p 8080:8080 -e OPENAI_API_KEY= embedchain/rest-api:latest -``` \ No newline at end of file diff --git a/embedchain/docs/examples/rest-api/delete.mdx b/embedchain/docs/examples/rest-api/delete.mdx deleted file mode 100644 index 3aada3398..000000000 --- a/embedchain/docs/examples/rest-api/delete.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -openapi: delete /{app_id}/delete ---- - - - - -```bash Request - curl --request DELETE \ - --url http://localhost:8080/{app_id}/delete -``` - - - - - -```json Response -{ "response": "App with id {app_id} deleted successfully." } -``` - - diff --git a/embedchain/docs/examples/rest-api/deploy.mdx b/embedchain/docs/examples/rest-api/deploy.mdx deleted file mode 100644 index b72f91da0..000000000 --- a/embedchain/docs/examples/rest-api/deploy.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -openapi: post /{app_id}/deploy ---- - - - - -```bash Request -curl --request POST \ - --url http://localhost:8080/{app_id}/deploy \ - -d "api_key=ec-xxxx" -``` - - - - - -```json Response -{ "response": "App deployed successfully." } -``` - - diff --git a/embedchain/docs/examples/rest-api/get-all-apps.mdx b/embedchain/docs/examples/rest-api/get-all-apps.mdx deleted file mode 100644 index 6f603f9a6..000000000 --- a/embedchain/docs/examples/rest-api/get-all-apps.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -openapi: get /apps ---- - - - -```bash Request -curl --request GET \ - --url http://localhost:8080/apps -``` - - - - - -```json Response -{ - "results": [ - { - "config": "config1.yaml", - "id": 1, - "app_id": "app1" - }, - { - "config": "config2.yaml", - "id": 2, - "app_id": "app2" - } - ] -} -``` - - diff --git a/embedchain/docs/examples/rest-api/get-data.mdx b/embedchain/docs/examples/rest-api/get-data.mdx deleted file mode 100644 index 0c960e6cb..000000000 --- a/embedchain/docs/examples/rest-api/get-data.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -openapi: get /{app_id}/data ---- - - - -```bash Request -curl --request GET \ - --url http://localhost:8080/{app_id}/data -``` - - - - - -```json Response -{ - "results": [ - { - "data_type": "web_page", - "data_value": "https://www.forbes.com/profile/elon-musk/", - "metadata": "null" - } - ] -} -``` - - diff --git a/embedchain/docs/examples/rest-api/getting-started.mdx b/embedchain/docs/examples/rest-api/getting-started.mdx deleted file mode 100644 index 5501792b6..000000000 --- a/embedchain/docs/examples/rest-api/getting-started.mdx +++ /dev/null @@ -1,294 +0,0 @@ ---- -title: "🌍 Getting Started" ---- - -## Quickstart - -To use Embedchain as a REST API service, run the following command: - -```bash -docker run --name embedchain -p 8080:8080 embedchain/rest-api:latest -``` - -Navigate to [http://localhost:8080/docs](http://localhost:8080/docs) to interact with the API. There is a full-fledged Swagger docs playground with all the information about the API endpoints. - -![Swagger Docs Screenshot](https://github.com/embedchain/embedchain/assets/73601258/299d81e5-a0df-407c-afc2-6fa2c4286844) - -## ⚡ Steps to get started - - - - - - ```bash - curl --request POST "http://localhost:8080/create?app_id=my-app" \ - -H "accept: application/json" - ``` - - - ```python - import requests - - url = "http://localhost:8080/create?app_id=my-app" - - payload={} - - response = requests.request("POST", url, data=payload) - - print(response) - ``` - - - ```javascript - const data = fetch("http://localhost:8080/create?app_id=my-app", { - method: "POST", - }).then((res) => res.json()); - - console.log(data); - ``` - - - ```go - package main - - import ( - "fmt" - "net/http" - "io/ioutil" - ) - - func main() { - - url := "http://localhost:8080/create?app_id=my-app" - - payload := strings.NewReader("") - - req, _ := http.NewRequest("POST", url, payload) - - req.Header.Add("Content-Type", "application/json") - - res, _ := http.DefaultClient.Do(req) - - defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) - - fmt.Println(res) - fmt.Println(string(body)) - - } - ``` - - - - - - - - ```bash - curl --request POST \ - --url http://localhost:8080/my-app/add \ - -d "source=https://www.forbes.com/profile/elon-musk" \ - -d "data_type=web_page" - ``` - - - ```python - import requests - - url = "http://localhost:8080/my-app/add" - - payload = "source=https://www.forbes.com/profile/elon-musk&data_type=web_page" - headers = {} - - response = requests.request("POST", url, headers=headers, data=payload) - - print(response) - ``` - - - ```javascript - const data = fetch("http://localhost:8080/my-app/add", { - method: "POST", - body: "source=https://www.forbes.com/profile/elon-musk&data_type=web_page", - }).then((res) => res.json()); - - console.log(data); - ``` - - - ```go - package main - - import ( - "fmt" - "strings" - "net/http" - "io/ioutil" - ) - - func main() { - - url := "http://localhost:8080/my-app/add" - - payload := strings.NewReader("source=https://www.forbes.com/profile/elon-musk&data_type=web_page") - - req, _ := http.NewRequest("POST", url, payload) - - req.Header.Add("Content-Type", "application/x-www-form-urlencoded") - - res, _ := http.DefaultClient.Do(req) - - defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) - - fmt.Println(res) - fmt.Println(string(body)) - - } - ``` - - - - - - - - ```bash - curl --request POST \ - --url http://localhost:8080/my-app/query \ - -d "query=Who is Elon Musk?" - ``` - - - ```python - import requests - - url = "http://localhost:8080/my-app/query" - - payload = "query=Who is Elon Musk?" - headers = {} - - response = requests.request("POST", url, headers=headers, data=payload) - - print(response) - ``` - - - ```javascript - const data = fetch("http://localhost:8080/my-app/query", { - method: "POST", - body: "query=Who is Elon Musk?", - }).then((res) => res.json()); - - console.log(data); - ``` - - - ```go - package main - - import ( - "fmt" - "strings" - "net/http" - "io/ioutil" - ) - - func main() { - - url := "http://localhost:8080/my-app/query" - - payload := strings.NewReader("query=Who is Elon Musk?") - - req, _ := http.NewRequest("POST", url, payload) - - req.Header.Add("Content-Type", "application/x-www-form-urlencoded") - - res, _ := http.DefaultClient.Do(req) - - defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) - - fmt.Println(res) - fmt.Println(string(body)) - - } - ``` - - - - - - - - ```bash - curl --request POST \ - --url http://localhost:8080/my-app/deploy \ - -d "api_key=ec-xxxx" - ``` - - - ```python - import requests - - url = "http://localhost:8080/my-app/deploy" - - payload = "api_key=ec-xxxx" - - response = requests.request("POST", url, data=payload) - - print(response) - ``` - - - ```javascript - const data = fetch("http://localhost:8080/my-app/deploy", { - method: "POST", - body: "api_key=ec-xxxx", - }).then((res) => res.json()); - - console.log(data); - ``` - - - ```go - package main - - import ( - "fmt" - "strings" - "net/http" - "io/ioutil" - ) - - func main() { - - url := "http://localhost:8080/my-app/deploy" - - payload := strings.NewReader("api_key=ec-xxxx") - - req, _ := http.NewRequest("POST", url, payload) - - req.Header.Add("Content-Type", "application/x-www-form-urlencoded") - - res, _ := http.DefaultClient.Do(req) - - defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) - - fmt.Println(res) - fmt.Println(string(body)) - - } - ``` - - - - - - -And you're ready! 🎉 - -If you run into issues, please feel free to contact us using below links: - - diff --git a/embedchain/docs/examples/rest-api/query.mdx b/embedchain/docs/examples/rest-api/query.mdx deleted file mode 100644 index 2d647e505..000000000 --- a/embedchain/docs/examples/rest-api/query.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -openapi: post /{app_id}/query ---- - - - -```bash Request -curl --request POST \ - --url http://localhost:8080/{app_id}/query \ - -d "query=who is Elon Musk?" -``` - - - - - -```json Response -{ "response": "Net worth of Elon Musk is $218 Billion." } -``` - - diff --git a/embedchain/docs/examples/showcase.mdx b/embedchain/docs/examples/showcase.mdx deleted file mode 100644 index d614c3b00..000000000 --- a/embedchain/docs/examples/showcase.mdx +++ /dev/null @@ -1,115 +0,0 @@ ---- -title: '🎪 Community showcase' ---- - -Embedchain community has been super active in creating demos on top of Embedchain. On this page, we showcase all the apps, blogs, videos, and tutorials created by the community. ❤️ - -## Apps - -### Open Source - -- [My GSoC23 bot- Streamlit chat](https://github.com/lucifertrj/EmbedChain_GSoC23_BOT) by Tarun Jain -- [Discord Bot for LLM chat](https://github.com/Reidond/discord_bots_playground/tree/c8b0c36541e4b393782ee506804c4b6962426dd6/python/chat-channel-bot) by Reidond -- [EmbedChain-Streamlit-Docker App](https://github.com/amjadraza/embedchain-streamlit-app) by amjadraza -- [Harry Potter Philosphers Stone Bot](https://github.com/vinayak-kempawad/Harry_Potter_Philosphers_Stone_Bot/) by Vinayak Kempawad, ([LinkedIn post](https://www.linkedin.com/feed/update/urn:li:activity:7080907532155686912/)) -- [LLM bot trained on own messages](https://github.com/Harin329/harinBot) by Hao Wu - -### Closed Source - -- [Taobot.io](https://taobot.io) - chatbot & knowledgebase hybrid by [cachho](https://github.com/cachho) -- [Create Instant ChatBot 🤖 using embedchain](https://databutton.com/v/h3e680h9) by Avra, ([Tweet](https://twitter.com/Avra_b/status/1674704745154641920/)) -- [JOBO 🤖 — The AI-driven sidekick to craft your resume](https://try-jobo.com/) by Enrico Willemse, ([LinkedIn Post](https://www.linkedin.com/posts/enrico-willemse_jobai-gptfun-embedchain-activity-7090340080879374336-ueLB/)) -- [Explore Your Knowledge Base: Interactive chats over various forms of documents](https://chatdocs.dkedar.com/) by Kedar Dabhadkar, ([LinkedIn Post](https://www.linkedin.com/posts/dkedar7_machinelearning-llmops-activity-7092524836639424513-2O3L/)) -- [Chatbot trained on 1000+ videos of Ester hicks the co-author behind the famous book Secret](https://askabraham.tokenofme.io/) by Mohan Kumar - - -## Templates - -### Replit -- [Embedchain Chat Bot](https://replit.com/@taranjeet1/Embedchain-Chat-Bot) by taranjeetio -- [Embedchain Memory Chat Bot Template](https://replit.com/@taranjeetio/Embedchain-Memory-Chat-Bot-Template) by taranjeetio -- [Chatbot app to demonstrate question-answering using retrieved information](https://replit.com/@AllisonMorrell/EmbedChainlitPublic) by Allison Morrell, ([LinkedIn Post](https://www.linkedin.com/posts/allison-morrell-2889275a_retrievalbot-screenshots-activity-7080339991754649600-wihZ/)) - -## Posts - -### Blogs - -- [Customer Service LINE Bot](https://www.evanlin.com/langchain-embedchain/) by Evan Lin -- [Chatbot in Under 5 mins using Embedchain](https://medium.com/@ayush.wattal/chatbot-in-under-5-mins-using-embedchain-a4f161fcf9c5) by Ayush Wattal -- [Understanding what the LLM framework embedchain does](https://zenn.dev/hijikix/articles/4bc8d60156a436) by Daisuke Hashimoto -- [In bed with GPT and Node.js](https://dev.to/worldlinetech/in-bed-with-gpt-and-nodejs-4kh2) by Raphaël Semeteys, ([LinkedIn Post](https://www.linkedin.com/posts/raphaelsemeteys_in-bed-with-gpt-and-nodejs-activity-7088113552326029313-nn87/)) -- [Using Embedchain — A powerful LangChain Python wrapper to build Chat Bots even faster!⚡](https://medium.com/@avra42/using-embedchain-a-powerful-langchain-python-wrapper-to-build-chat-bots-even-faster-35c12994a360) by Avra, ([Tweet](https://twitter.com/Avra_b/status/1686767751560310784/)) -- [What is the Embedchain library?](https://jahaniwww.com/%da%a9%d8%aa%d8%a7%d8%a8%d8%ae%d8%a7%d9%86%d9%87-embedchain/) by Ali Jahani, ([LinkedIn Post](https://www.linkedin.com/posts/ajahani_aepaetaeqaexaggahyaeu-aetaexaesabraeaaeqaepaeu-activity-7097605202135904256-ppU-/)) -- [LangChain is Nice, But Have You Tried EmbedChain ?](https://medium.com/thoughts-on-machine-learning/langchain-is-nice-but-have-you-tried-embedchain-215a34421cde) by FS Ndzomga, ([Tweet](https://twitter.com/ndzfs/status/1695583640372035951/)) -- [Simplest Method to Build a Custom Chatbot with GPT-3.5 (via Embedchain)](https://www.ainewsletter.today/p/simplest-method-to-build-a-custom) by Arjun, ([Tweet](https://twitter.com/aiguy_arjun/status/1696393808467091758/)) - -### LinkedIn - -- [What is embedchain](https://www.linkedin.com/posts/activity-7079393104423698432-wRyi/) by Rithesh Sreenivasan -- [Building a chatbot with EmbedChain](https://www.linkedin.com/posts/activity-7078434598984060928-Zdso/) by Lior Sinclair -- [Making chatbot without vs with embedchain](https://www.linkedin.com/posts/kalyanksnlp_llms-chatbots-langchain-activity-7077453416221863936-7N1L/) by Kalyan KS -- [EmbedChain - very intuitive, first you index your data and then query!](https://www.linkedin.com/posts/shubhamsaboo_embedchain-a-framework-to-easily-create-activity-7079535460699557888-ad1X/) by Shubham Saboo -- [EmbedChain - Harnessing power of LLM](https://www.linkedin.com/posts/uditsaini_chatbotrevolution-llmpoweredbots-embedchainframework-activity-7077520356827181056-FjTK/) by Udit S. -- [AI assistant for ABBYY Vantage](https://www.linkedin.com/posts/maximevermeir_llm-github-abbyy-activity-7081658972071424000-fXfZ/) by Maxime V. -- [About embedchain](https://www.linkedin.com/feed/update/urn:li:activity:7080984218914189312/) by Morris Lee -- [How to use Embedchain](https://www.linkedin.com/posts/nehaabansal_github-embedchainembedchain-framework-activity-7085830340136595456-kbW5/) by Neha Bansal -- [Youtube/Webpage summary for Energy Study](https://www.linkedin.com/posts/bar%C4%B1%C5%9F-sanl%C4%B1-34b82715_enerji-python-activity-7082735341563977730-Js0U/) by Barış Sanlı, ([Tweet](https://twitter.com/barissanli/status/1676968784979193857/)) -- [Demo: How to use Embedchain? (Contains Collab Notebook link)](https://www.linkedin.com/posts/liorsinclair_embedchain-is-getting-a-lot-of-traction-because-activity-7103044695995424768-RckT/) by Lior Sinclair - -### Twitter - -- [What is embedchain](https://twitter.com/AlphaSignalAI/status/1672668574450847745) by Lior -- [Building a chatbot with Embedchain](https://twitter.com/Saboo_Shubham_/status/1673537044419686401) by Shubham Saboo -- [Chatbot docker image behind an API with yaml configs with Embedchain](https://twitter.com/tricalt/status/1678411430192730113/) by Vasilije -- [Build AI powered PDF chatbot with just five lines of Python code with Embedchain!](https://twitter.com/Saboo_Shubham_/status/1676627104866156544/) by Shubham Saboo -- [Chatbot against a youtube video using embedchain](https://twitter.com/smaameri/status/1675201443043704834/) by Sami Maameri -- [Highlights of EmbedChain](https://twitter.com/carl_AIwarts/status/1673542204328120321/) by carl_AIwarts -- [Build Llama-2 chatbot in less than 5 minutes](https://twitter.com/Saboo_Shubham_/status/1682168956918833152/) by Shubham Saboo -- [All cool features of embedchain](https://twitter.com/DhravyaShah/status/1683497882438217728/) by Dhravya Shah, ([LinkedIn Post](https://www.linkedin.com/posts/dhravyashah_what-if-i-tell-you-that-you-can-make-an-ai-activity-7089459599287726080-ZIYm/)) -- [Read paid Medium articles for Free using embedchain](https://twitter.com/kumarkaushal_/status/1688952961622585344) by Kaushal Kumar - -## Videos - -- [Embedchain in one shot](https://www.youtube.com/watch?v=vIhDh7H73Ww&t=82s) by AI with Tarun -- [embedChain Create LLM powered bots over any dataset Python Demo Tesla Neurallink Chatbot Example](https://www.youtube.com/watch?v=bJqAn22a6Gc) by Rithesh Sreenivasan -- [Embedchain - NEW 🔥 Langchain BABY to build LLM Bots](https://www.youtube.com/watch?v=qj_GNQ06I8o) by 1littlecoder -- [EmbedChain -- NEW!: Build LLM-Powered Bots with Any Dataset](https://www.youtube.com/watch?v=XmaBezzGHu4) by DataInsightEdge -- [Chat With Your PDFs in less than 10 lines of code! EMBEDCHAIN tutorial](https://www.youtube.com/watch?v=1ugkcsAcw44) by Phani Reddy -- [How To Create A Custom Knowledge AI Powered Bot | Install + How To Use](https://www.youtube.com/watch?v=VfCrIiAst-c) by The Ai Solopreneur -- [Build Custom Chatbot in 6 min with this Framework [Beginner Friendly]](https://www.youtube.com/watch?v=-8HxOpaFySM) by Maya Akim -- [embedchain-streamlit-app](https://www.youtube.com/watch?v=3-9GVd-3v74) by Amjad Raza -- [🤖CHAT with ANY ONLINE RESOURCES using EMBEDCHAIN - a LangChain wrapper, in few lines of code !](https://www.youtube.com/watch?v=Mp7zJe4TIdM) by Avra -- [Building resource-driven LLM-powered bots with Embedchain](https://www.youtube.com/watch?v=IVfcAgxTO4I) by BugBytes -- [embedchain-streamlit-demo](https://www.youtube.com/watch?v=yJAWB13FhYQ) by Amjad Raza -- [Embedchain - create your own AI chatbots using open source models](https://www.youtube.com/shorts/O3rJWKwSrWE) by Dhravya Shah -- [AI ChatBot in 5 lines Python Code](https://www.youtube.com/watch?v=zjWvLJLksv8) by Data Engineering -- [Interview with Karl Marx](https://www.youtube.com/watch?v=5Y4Tscwj1xk) by Alexander Ray Williams -- [Vlog where we try to build a bot based on our content on the internet](https://www.youtube.com/watch?v=I2w8CWM3bx4) by DV, ([Tweet](https://twitter.com/dvcoolster/status/1688387017544261632)) -- [CHAT with ANY ONLINE RESOURCES using EMBEDCHAIN|STREAMLIT with MEMORY |All OPENSOURCE](https://www.youtube.com/watch?v=TqQIHWoWTDQ&pp=ygUKZW1iZWRjaGFpbg%3D%3D) by DataInsightEdge -- [Build POWERFUL LLM Bots EASILY with Your Own Data - Embedchain - Langchain 2.0? (Tutorial)](https://www.youtube.com/watch?v=jE24Y_GasE8) by WorldofAI, ([Tweet](https://twitter.com/intheworldofai/status/1696229166922780737)) -- [Embedchain: An AI knowledge base assistant for customizing enterprise private data, which can be connected to discord, whatsapp, slack, tele and other terminals (with gradio to build a request interface) in Chinese](https://www.youtube.com/watch?v=5RZzCJRk-d0) by AIGC LINK -- [Embedchain Introduction](https://www.youtube.com/watch?v=Jet9zAqyggI) by Fahd Mirza - -## Mentions - -### Github repos - -- [Awesome-LLM](https://github.com/Hannibal046/Awesome-LLM) -- [awesome-chatgpt-api](https://github.com/reorx/awesome-chatgpt-api) -- [awesome-langchain](https://github.com/kyrolabs/awesome-langchain) -- [Awesome-Prompt-Engineering](https://github.com/promptslab/Awesome-Prompt-Engineering) -- [awesome-chatgpt](https://github.com/eon01/awesome-chatgpt) -- [Awesome-LLMOps](https://github.com/tensorchord/Awesome-LLMOps) -- [awesome-generative-ai](https://github.com/filipecalegario/awesome-generative-ai) -- [awesome-gpt](https://github.com/formulahendry/awesome-gpt) -- [awesome-ChatGPT-repositories](https://github.com/taishi-i/awesome-ChatGPT-repositories) -- [awesome-gpt-prompt-engineering](https://github.com/snwfdhmp/awesome-gpt-prompt-engineering) -- [awesome-chatgpt](https://github.com/awesome-chatgpt/awesome-chatgpt) -- [awesome-llm-and-aigc](https://github.com/sjinzh/awesome-llm-and-aigc) -- [awesome-compbio-chatgpt](https://github.com/csbl-br/awesome-compbio-chatgpt) -- [Awesome-LLM4Tool](https://github.com/OpenGVLab/Awesome-LLM4Tool) - -## Meetups - -- [Dash and ChatGPT: Future of AI-enabled apps 30/08/23](https://go.plotly.com/dash-chatgpt) -- [Pie & AI: Bangalore - Build end-to-end LLM app using Embedchain 01/09/23](https://www.eventbrite.com/e/pie-ai-bangalore-build-end-to-end-llm-app-using-embedchain-tickets-698045722547) diff --git a/embedchain/docs/examples/slack-AI.mdx b/embedchain/docs/examples/slack-AI.mdx deleted file mode 100644 index 7efaba279..000000000 --- a/embedchain/docs/examples/slack-AI.mdx +++ /dev/null @@ -1,67 +0,0 @@ -[Embedchain Examples Repo](https://github.com/embedchain/examples) contains code on how to build your own Slack AI to chat with the unstructured data lying in your slack channels. - -![Slack AI Demo](/images/slack-ai.png) - -## Getting started - -Create a Slack AI involves 3 steps - -* Create slack user -* Set environment variables -* Run the app locally - -### Step 1: Create Slack user token - -Follow the steps given below to fetch your slack user token to get data through Slack APIs: - -1. Create a workspace on Slack if you don’t have one already by clicking [here](https://slack.com/intl/en-in/). -2. Create a new App on your Slack account by going [here](https://api.slack.com/apps). -3. Select `From Scratch`, then enter the App Name and select your workspace. -4. Navigate to `OAuth & Permissions` tab from the left sidebar and go to the `scopes` section. Add the following scopes under `User Token Scopes`: - - ``` - # Following scopes are needed for reading channel history - channels:history - channels:read - - # Following scopes are needed to fetch list of channels from slack - groups:read - mpim:read - im:read - ``` - -5. Click on the `Install to Workspace` button under `OAuth Tokens for Your Workspace` section in the same page and install the app in your slack workspace. -6. After installing the app you will see the `User OAuth Token`, save that token as you will need to configure it as `SLACK_USER_TOKEN` for this demo. - -### Step 2: Set environment variables - -Navigate to `api` folder and set your `HUGGINGFACE_ACCESS_TOKEN` and `SLACK_USER_TOKEN` in `.env.example` file. Then rename the `.env.example` file to `.env`. - - - -By default, we use `Mixtral` model from Hugging Face. However, if you prefer to use OpenAI model, then set `OPENAI_API_KEY` instead of `HUGGINGFACE_ACCESS_TOKEN` along with `SLACK_USER_TOKEN` in `.env` file, and update the code in `api/utils/app.py` file to use OpenAI model instead of Hugging Face model. - - -### Step 3: Run app locally - -Follow the instructions given below to run app locally based on your development setup (with docker or without docker): - -#### With docker - -```bash -docker-compose build -ec start --docker -``` - -#### Without docker - -```bash -ec install-reqs -ec start -``` - -Finally, you will have the Slack AI frontend running on http://localhost:3000. You can also access the REST APIs on http://localhost:8000. - -## Credits - -This demo was built using the Embedchain's [full stack demo template](https://docs.embedchain.ai/get-started/full-stack). Follow the instructions [given here](https://docs.embedchain.ai/get-started/full-stack) to create your own full stack RAG application. diff --git a/embedchain/docs/examples/slack_bot.mdx b/embedchain/docs/examples/slack_bot.mdx deleted file mode 100644 index 034c821d2..000000000 --- a/embedchain/docs/examples/slack_bot.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: '💼 Slack Bot' ---- - -### 🖼️ Setup - -1. Create a workspace on Slack if you don't have one already by clicking [here](https://slack.com/intl/en-in/). -2. Create a new App on your Slack account by going [here](https://api.slack.com/apps). -3. Select `From Scratch`, then enter the Bot Name and select your workspace. -4. On the left Sidebar, go to `OAuth and Permissions` and add the following scopes under `Bot Token Scopes`: -```text -app_mentions:read -channels:history -channels:read -chat:write -``` -5. Now select the option `Install to Workspace` and after it's done, copy the `Bot User OAuth Token` and set it in your secrets as `SLACK_BOT_TOKEN`. -6. Run your bot now, - - - ```bash - docker run --name slack-bot -e OPENAI_API_KEY=sk-xxx -e SLACK_BOT_TOKEN=xxx -p 8000:8000 embedchain/slack-bot - ``` - - - ```bash - pip install --upgrade "embedchain[slack]" - python3 -m embedchain.bots.slack --port 8000 - ``` - - -7. Expose your bot to the internet. You can use your machine's public IP or DNS. Otherwise, employ a proxy server like [ngrok](https://ngrok.com/) to make your local bot accessible. -8. On the Slack API website go to `Event Subscriptions` on the left Sidebar and turn on `Enable Events`. -9. In `Request URL`, enter your server or ngrok address. -10. After it gets verified, click on `Subscribe to bot events`, add `message.channels` Bot User Event and click on `Save Changes`. -11. Now go to your workspace, right click on the bot name in the sidebar, click `view app details`, then `add this app to a channel`. - -### 🚀 Usage Instructions - -- Go to the channel where you have added your bot. -- To add data sources to the bot, use the command: -```text -add -``` -- To ask queries from the bot, use the command: -```text -query -``` - -🎉 Happy Chatting! 🎉 diff --git a/embedchain/docs/examples/telegram_bot.mdx b/embedchain/docs/examples/telegram_bot.mdx deleted file mode 100644 index 14f17e90c..000000000 --- a/embedchain/docs/examples/telegram_bot.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: "📱 Telegram Bot" ---- - -### 🖼️ Template Setup - -- Open the Telegram app and search for the `BotFather` user. -- Start a chat with BotFather and use the `/newbot` command to create a new bot. -- Follow the instructions to choose a name and username for your bot. -- Once the bot is created, BotFather will provide you with a unique token for your bot. - - - - ```bash - docker run --name telegram-bot -e OPENAI_API_KEY=sk-xxx -e TELEGRAM_BOT_TOKEN=xxx -p 8000:8000 embedchain/telegram-bot - ``` - - - If you wish to use **Docker**, you would need to host your bot on a server. - You can use [ngrok](https://ngrok.com/) to expose your localhost to the - internet and then set the webhook using the ngrok URL. - - - - - - Fork **[this](https://replit.com/@taranjeetio/EC-Telegram-Bot-Template?v=1#README.md)** replit template. - - - - Set your `OPENAI_API_KEY` in Secrets. - - Set the unique token as `TELEGRAM_BOT_TOKEN` in Secrets. - - - - - -- Click on `Run` in the replit container and a URL will get generated for your bot. -- Now set your webhook by running the following link in your browser: - -```url -https://api.telegram.org/bot/setWebhook?url= -``` - -- When you get a successful response in your browser, your bot is ready to be used. - -### 🚀 Usage Instructions - -- Open your bot by searching for it using the bot name or bot username. -- Click on `Start` or type `/start` and follow the on screen instructions. - -🎉 Happy Chatting! 🎉 diff --git a/embedchain/docs/examples/whatsapp_bot.mdx b/embedchain/docs/examples/whatsapp_bot.mdx deleted file mode 100644 index 16a8c504a..000000000 --- a/embedchain/docs/examples/whatsapp_bot.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: '💬 WhatsApp Bot' ---- - -### 🚀 Getting started - -1. Install embedchain python package: - -```bash -pip install --upgrade embedchain -``` - -2. Launch your WhatsApp bot: - - - - ```bash - docker run --name whatsapp-bot -e OPENAI_API_KEY=sk-xxx -p 8000:8000 embedchain/whatsapp-bot - ``` - - - ```bash - python -m embedchain.bots.whatsapp --port 5000 - ``` - - - - -If your bot needs to be accessible online, use your machine's public IP or DNS. Otherwise, employ a proxy server like [ngrok](https://ngrok.com/) to make your local bot accessible. - -3. Create a free account on [Twilio](https://www.twilio.com/try-twilio) - - Set up a WhatsApp Sandbox in your Twilio dashboard. Access it via the left sidebar: `Messaging > Try it out > Send a WhatsApp Message`. - - Follow on-screen instructions to link a phone number for chatting with your bot - - Copy your bot's public URL, add /chat at the end, and paste it in Twilio's WhatsApp Sandbox settings under "When a message comes in". Save the settings. - -- Copy your bot's public url, append `/chat` at the end and paste it under `When a message comes in` under the `Sandbox settings` for Whatsapp in Twilio. Save your settings. - -### 💬 How to use - -- To connect a new number or reconnect an old one in the Sandbox, follow Twilio's instructions. -- To include data sources, use this command: -```text -add -``` - -- To ask the bot questions, just type your query: -```text - -``` - -### Example - -Here is an example of Elon Musk WhatsApp Bot that we created: - - diff --git a/embedchain/docs/favicon.png b/embedchain/docs/favicon.png deleted file mode 100644 index 35494d9ea..000000000 Binary files a/embedchain/docs/favicon.png and /dev/null differ diff --git a/embedchain/docs/get-started/deployment.mdx b/embedchain/docs/get-started/deployment.mdx deleted file mode 100644 index 87e72dcbb..000000000 --- a/embedchain/docs/get-started/deployment.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: 'Overview' -description: 'Deploy your RAG application to production' ---- - -After successfully setting up and testing your RAG app locally, the next step is to deploy it to a hosting service to make it accessible to a wider audience. Embedchain provides integration with different cloud providers so that you can seamlessly deploy your RAG applications to production without having to worry about going through the cloud provider instructions. Embedchain does all the heavy lifting for you. - - - - - - - - - - - -## Seeking help? - -If you run into issues with deployment, please feel free to reach out to us via any of the following methods: - - diff --git a/embedchain/docs/get-started/faq.mdx b/embedchain/docs/get-started/faq.mdx deleted file mode 100644 index 3acae2671..000000000 --- a/embedchain/docs/get-started/faq.mdx +++ /dev/null @@ -1,191 +0,0 @@ ---- -title: ❓ FAQs -description: 'Collections of all the frequently asked questions' ---- - - -Yes, it does. Please refer to the [OpenAI Assistant docs page](/examples/openai-assistant). - - -Use the model provided on huggingface: `mistralai/Mistral-7B-v0.1` - -```python main.py -import os -from embedchain import App - -os.environ["HUGGINGFACE_ACCESS_TOKEN"] = "hf_your_token" - -app = App.from_config("huggingface.yaml") -``` -```yaml huggingface.yaml -llm: - provider: huggingface - config: - model: 'mistralai/Mistral-7B-v0.1' - temperature: 0.5 - max_tokens: 1000 - top_p: 0.5 - stream: false - -embedder: - provider: huggingface - config: - model: 'sentence-transformers/all-mpnet-base-v2' -``` - - - -Use the model `gpt-4-turbo` provided my openai. - - -```python main.py -import os -from embedchain import App - -os.environ['OPENAI_API_KEY'] = 'xxx' - -# load llm configuration from gpt4_turbo.yaml file -app = App.from_config(config_path="gpt4_turbo.yaml") -``` - -```yaml gpt4_turbo.yaml -llm: - provider: openai - config: - model: 'gpt-4-turbo' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false -``` - - - - - -```python main.py -import os -from embedchain import App - -os.environ['OPENAI_API_KEY'] = 'xxx' - -# load llm configuration from gpt4.yaml file -app = App.from_config(config_path="gpt4.yaml") -``` - -```yaml gpt4.yaml -llm: - provider: openai - config: - model: 'gpt-4' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false -``` - - - - - - -```python main.py -from embedchain import App - -# load llm configuration from opensource.yaml file -app = App.from_config(config_path="opensource.yaml") -``` - -```yaml opensource.yaml -llm: - provider: gpt4all - config: - model: 'orca-mini-3b-gguf2-q4_0.gguf' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -embedder: - provider: gpt4all - config: - model: 'all-MiniLM-L6-v2' -``` - - - - -You can achieve this by setting `stream` to `true` in the config file. - - -```yaml openai.yaml -llm: - provider: openai - config: - model: 'gpt-4o-mini' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: true -``` - -```python main.py -import os -from embedchain import App - -os.environ['OPENAI_API_KEY'] = 'sk-xxx' - -app = App.from_config(config_path="openai.yaml") - -app.add("https://www.forbes.com/profile/elon-musk") - -response = app.query("What is the net worth of Elon Musk?") -# response will be streamed in stdout as it is generated. -``` - - - - - Set up the app by adding an `id` in the config file. This keeps the data for future use. You can include this `id` in the yaml config or input it directly in `config` dict. - ```python app1.py - import os - from embedchain import App - - os.environ['OPENAI_API_KEY'] = 'sk-xxx' - - app1 = App.from_config(config={ - "app": { - "config": { - "id": "your-app-id", - } - } - }) - - app1.add("https://www.forbes.com/profile/elon-musk") - - response = app1.query("What is the net worth of Elon Musk?") - ``` - ```python app2.py - import os - from embedchain import App - - os.environ['OPENAI_API_KEY'] = 'sk-xxx' - - app2 = App.from_config(config={ - "app": { - "config": { - # this will persist and load data from app1 session - "id": "your-app-id", - } - } - }) - - response = app2.query("What is the net worth of Elon Musk?") - ``` - - - -#### Still have questions? -If docs aren't sufficient, please feel free to reach out to us using one of the following methods: - - diff --git a/embedchain/docs/get-started/full-stack.mdx b/embedchain/docs/get-started/full-stack.mdx deleted file mode 100644 index cd45a0b9e..000000000 --- a/embedchain/docs/get-started/full-stack.mdx +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: '💻 Full stack' ---- - -Get started with full-stack RAG applications using Embedchain's easy-to-use CLI tool. Set up everything with just a few commands, whether you prefer Docker or not. - -## Prerequisites - -Choose your setup method: - -* [Without docker](#without-docker) -* [With Docker](#with-docker) - -### Without Docker - -Ensure these are installed: - -- Embedchain python package (`pip install embedchain`) -- [Node.js](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) and [Yarn](https://classic.yarnpkg.com/lang/en/docs/install/) - -### With Docker - -Install Docker from [Docker's official website](https://docs.docker.com/engine/install/). - -## Quick Start Guide - -### Install the package - -Before proceeding, make sure you have the Embedchain package installed. - -```bash -pip install embedchain -U -``` - -### Setting Up - -For the purpose of the demo, you have to set `OPENAI_API_KEY` to start with but you can choose any llm by changing the configuration easily. - -### Installation Commands - - - -```bash without docker -ec create-app my-app -cd my-app -ec start -``` - -```bash with docker -ec create-app my-app --docker -cd my-app -ec start --docker -``` - - - -### What Happens Next? - -1. Embedchain fetches a full stack template (FastAPI backend, Next.JS frontend). -2. Installs required components. -3. Launches both frontend and backend servers. - -### See It In Action - -Open http://localhost:3000 to view the chat UI. - -![full stack example](/images/fullstack.png) - -### Admin Panel - -Check out the Embedchain admin panel to see the document chunks for your RAG application. - -![full stack chunks](/images/fullstack-chunks.png) - -### API Server - -If you want to access the API server, you can do so at http://localhost:8000/docs. - -![API Server](/images/fullstack-api-server.png) - -You can customize the UI and code as per your requirements. diff --git a/embedchain/docs/get-started/integrations.mdx b/embedchain/docs/get-started/integrations.mdx deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/docs/get-started/introduction.mdx b/embedchain/docs/get-started/introduction.mdx deleted file mode 100644 index fc7ce22ed..000000000 --- a/embedchain/docs/get-started/introduction.mdx +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: 📚 Introduction ---- - -## What is Embedchain? - -Embedchain is an Open Source Framework that makes it easy to create and deploy personalized AI apps. At its core, Embedchain follows the design principle of being *"Conventional but Configurable"* to serve both software engineers and machine learning engineers. - -Embedchain streamlines the creation of personalized LLM applications, offering a seamless process for managing various types of unstructured data. It efficiently segments data into manageable chunks, generates relevant embeddings, and stores them in a vector database for optimized retrieval. With a suite of diverse APIs, it enables users to extract contextual information, find precise answers, or engage in interactive chat conversations, all tailored to their own data. - -## Who is Embedchain for? - -Embedchain is designed for a diverse range of users, from AI professionals like Data Scientists and Machine Learning Engineers to those just starting their AI journey, including college students, independent developers, and hobbyists. Essentially, it's for anyone with an interest in AI, regardless of their expertise level. - -Our APIs are user-friendly yet adaptable, enabling beginners to effortlessly create LLM-powered applications with as few as 4 lines of code. At the same time, we offer extensive customization options for every aspect of building a personalized AI application. This includes the choice of LLMs, vector databases, loaders and chunkers, retrieval strategies, re-ranking, and more. - -Our platform's clear and well-structured abstraction layers ensure that users can tailor the system to meet their specific needs, whether they're crafting a simple project or a complex, nuanced AI application. - -## Why Use Embedchain? - -Developing a personalized AI application for production use presents numerous complexities, such as: - -- Integrating and indexing data from diverse sources. -- Determining optimal data chunking methods for each source. -- Synchronizing the RAG pipeline with regularly updated data sources. -- Implementing efficient data storage in a vector store. -- Deciding whether to include metadata with document chunks. -- Handling permission management. -- Configuring Large Language Models (LLMs). -- Selecting effective prompts. -- Choosing suitable retrieval strategies. -- Assessing the performance of your RAG pipeline. -- Deploying the pipeline into a production environment, among other concerns. - -Embedchain is designed to simplify these tasks, offering conventional yet customizable APIs. Our solution handles the intricate processes of loading, chunking, indexing, and retrieving data. This enables you to concentrate on aspects that are crucial for your specific use case or business objectives, ensuring a smoother and more focused development process. - -## How it works? - -Embedchain makes it easy to add data to your RAG pipeline with these straightforward steps: - -1. **Automatic Data Handling**: It automatically recognizes the data type and loads it. -2. **Efficient Data Processing**: The system creates embeddings for key parts of your data. -3. **Flexible Data Storage**: You get to choose where to store this processed data in a vector database. - -When a user asks a question, whether for chatting, searching, or querying, Embedchain simplifies the response process: - -1. **Query Processing**: It turns the user's question into embeddings. -2. **Document Retrieval**: These embeddings are then used to find related documents in the database. -3. **Answer Generation**: The related documents are used by the LLM to craft a precise answer. - -With Embedchain, you don’t have to worry about the complexities of building a personalized AI application. It offers an easy-to-use interface for developing applications with any kind of data. - -## Getting started - -Checkout our [quickstart guide](/get-started/quickstart) to start your first AI application. - -## Support - -Feel free to reach out to us if you have ideas, feedback or questions that we can help out with. - - - -## Contribute - -- [GitHub](https://github.com/embedchain/embedchain) -- [Contribution docs](/contribution/dev) diff --git a/embedchain/docs/get-started/quickstart.mdx b/embedchain/docs/get-started/quickstart.mdx deleted file mode 100644 index 04d270191..000000000 --- a/embedchain/docs/get-started/quickstart.mdx +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: '⚡ Quickstart' -description: '💡 Create an AI app on your own data in a minute' ---- - -## Installation - -First install the Python package: - -```bash -pip install embedchain -``` - -Once you have installed the package, depending upon your preference you can either use: - - - - This includes Open source LLMs like Mistral, Llama, etc.
- Free to use, and runs locally on your machine. -
- - This includes paid LLMs like GPT 4, Claude, etc.
- Cost money and are accessible via an API. -
-
- -## Open Source Models - -This section gives a quickstart example of using Mistral as the Open source LLM and Sentence transformers as the Open source embedding model. These models are free and run mostly on your local machine. - -We are using Mistral hosted at Hugging Face, so will you need a Hugging Face token to run this example. Its *free* and you can create one [here](https://huggingface.co/docs/hub/security-tokens). - - -```python huggingface_demo.py -import os -# Replace this with your HF token -os.environ["HUGGINGFACE_ACCESS_TOKEN"] = "hf_xxxx" - -from embedchain import App - -config = { - 'llm': { - 'provider': 'huggingface', - 'config': { - 'model': 'mistralai/Mistral-7B-Instruct-v0.2', - 'top_p': 0.5 - } - }, - 'embedder': { - 'provider': 'huggingface', - 'config': { - 'model': 'sentence-transformers/all-mpnet-base-v2' - } - } -} -app = App.from_config(config=config) -app.add("https://www.forbes.com/profile/elon-musk") -app.add("https://en.wikipedia.org/wiki/Elon_Musk") -app.query("What is the net worth of Elon Musk today?") -# Answer: The net worth of Elon Musk today is $258.7 billion. -``` - - -## Paid Models - -In this section, we will use both LLM and embedding model from OpenAI. - -```python openai_demo.py -import os -from embedchain import App - -# Replace this with your OpenAI key -os.environ["OPENAI_API_KEY"] = "sk-xxxx" - -app = App() -app.add("https://www.forbes.com/profile/elon-musk") -app.add("https://en.wikipedia.org/wiki/Elon_Musk") -app.query("What is the net worth of Elon Musk today?") -# Answer: The net worth of Elon Musk today is $258.7 billion. -``` - -# Next Steps - -Now that you have created your first app, you can follow any of the links: - -* [Introduction](/get-started/introduction) -* [Customization](/components/introduction) -* [Use cases](/use-cases/introduction) -* [Deployment](/get-started/deployment) diff --git a/embedchain/docs/images/checks-passed.png b/embedchain/docs/images/checks-passed.png deleted file mode 100644 index 3303c7736..000000000 Binary files a/embedchain/docs/images/checks-passed.png and /dev/null differ diff --git a/embedchain/docs/images/cover.gif b/embedchain/docs/images/cover.gif deleted file mode 100644 index efcc88243..000000000 Binary files a/embedchain/docs/images/cover.gif and /dev/null differ diff --git a/embedchain/docs/images/fly_io.png b/embedchain/docs/images/fly_io.png deleted file mode 100644 index 11a211afd..000000000 Binary files a/embedchain/docs/images/fly_io.png and /dev/null differ diff --git a/embedchain/docs/images/fullstack-api-server.png b/embedchain/docs/images/fullstack-api-server.png deleted file mode 100644 index 8b4ef2ac9..000000000 Binary files a/embedchain/docs/images/fullstack-api-server.png and /dev/null differ diff --git a/embedchain/docs/images/fullstack-chunks.png b/embedchain/docs/images/fullstack-chunks.png deleted file mode 100644 index ba4505ba7..000000000 Binary files a/embedchain/docs/images/fullstack-chunks.png and /dev/null differ diff --git a/embedchain/docs/images/fullstack.png b/embedchain/docs/images/fullstack.png deleted file mode 100644 index ba73bc067..000000000 Binary files a/embedchain/docs/images/fullstack.png and /dev/null differ diff --git a/embedchain/docs/images/gradio_app.png b/embedchain/docs/images/gradio_app.png deleted file mode 100644 index c5ed3cf4a..000000000 Binary files a/embedchain/docs/images/gradio_app.png and /dev/null differ diff --git a/embedchain/docs/images/helicone-embedchain.png b/embedchain/docs/images/helicone-embedchain.png deleted file mode 100644 index 05f61d73c..000000000 Binary files a/embedchain/docs/images/helicone-embedchain.png and /dev/null differ diff --git a/embedchain/docs/images/langsmith.png b/embedchain/docs/images/langsmith.png deleted file mode 100644 index 5d5ff5422..000000000 Binary files a/embedchain/docs/images/langsmith.png and /dev/null differ diff --git a/embedchain/docs/images/og.png b/embedchain/docs/images/og.png deleted file mode 100644 index 7a89999d3..000000000 Binary files a/embedchain/docs/images/og.png and /dev/null differ diff --git a/embedchain/docs/images/slack-ai.png b/embedchain/docs/images/slack-ai.png deleted file mode 100644 index cb2f137de..000000000 Binary files a/embedchain/docs/images/slack-ai.png and /dev/null differ diff --git a/embedchain/docs/images/whatsapp.jpg b/embedchain/docs/images/whatsapp.jpg deleted file mode 100644 index 6f28ba200..000000000 Binary files a/embedchain/docs/images/whatsapp.jpg and /dev/null differ diff --git a/embedchain/docs/integration/chainlit.mdx b/embedchain/docs/integration/chainlit.mdx deleted file mode 100644 index 6a28f309a..000000000 --- a/embedchain/docs/integration/chainlit.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: '⛓️ Chainlit' -description: 'Integrate with Chainlit to create LLM chat apps' ---- - -In this example, we will learn how to use Chainlit and Embedchain together. - -![chainlit-demo](https://github.com/embedchain/embedchain/assets/73601258/d6635624-5cdb-485b-bfbd-3b7c8f18bfff) - -## Setup - -First, install the required packages: - -```bash -pip install embedchain chainlit -``` - -## Create a Chainlit app - -Create a new file called `app.py` and add the following code: - -```python -import chainlit as cl -from embedchain import App - -import os - -os.environ["OPENAI_API_KEY"] = "sk-xxx" - -@cl.on_chat_start -async def on_chat_start(): - app = App.from_config(config={ - 'app': { - 'config': { - 'name': 'chainlit-app' - } - }, - 'llm': { - 'config': { - 'stream': True, - } - } - }) - # import your data here - app.add("https://www.forbes.com/profile/elon-musk/") - app.collect_metrics = False - cl.user_session.set("app", app) - - -@cl.on_message -async def on_message(message: cl.Message): - app = cl.user_session.get("app") - msg = cl.Message(content="") - for chunk in await cl.make_async(app.chat)(message.content): - await msg.stream_token(chunk) - - await msg.send() -``` - -## Run the app - -``` -chainlit run app.py -``` - -## Try it out - -Open the app in your browser and start chatting with it! diff --git a/embedchain/docs/integration/helicone.mdx b/embedchain/docs/integration/helicone.mdx deleted file mode 100644 index a5a33445a..000000000 --- a/embedchain/docs/integration/helicone.mdx +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "🧊 Helicone" -description: "Implement Helicone, the open-source LLM observability platform, with Embedchain. Monitor, debug, and optimize your AI applications effortlessly." -"twitter:title": "Helicone LLM Observability for Embedchain" ---- - -Get started with [Helicone](https://www.helicone.ai/), the open-source LLM observability platform for developers to monitor, debug, and optimize their applications. - -To use Helicone, you need to do the following steps. - -## Integration Steps - - - - Log into [Helicone](https://www.helicone.ai) or create an account. Once you have an account, you - can generate an [API key](https://helicone.ai/developer). - - - Make sure to generate a [write only API key](helicone-headers/helicone-auth). - - - - -You can configure your base_url and OpenAI API key in your codebase - - -```python main.py -import os -from embedchain import App - -# Modify the base path and add a Helicone URL -os.environ["OPENAI_API_BASE"] = "https://oai.helicone.ai/{YOUR_HELICONE_API_KEY}/v1" -# Add your OpenAI API Key -os.environ["OPENAI_API_KEY"] = "{YOUR_OPENAI_API_KEY}" - -app = App() - -# Add data to your app -app.add("https://en.wikipedia.org/wiki/Elon_Musk") - -# Query your app -print(app.query("How many companies did Elon found? Which companies?")) -``` - - - - - Embedchain requests - - - -Check out [Helicone](https://www.helicone.ai) to see more use cases! diff --git a/embedchain/docs/integration/langsmith.mdx b/embedchain/docs/integration/langsmith.mdx deleted file mode 100644 index 8a200be5b..000000000 --- a/embedchain/docs/integration/langsmith.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: '🛠️ LangSmith' -description: 'Integrate with Langsmith to debug and monitor your LLM app' ---- - -Embedchain now supports integration with [LangSmith](https://www.langchain.com/langsmith). - -To use LangSmith, you need to do the following steps. - -1. Have an account on LangSmith and keep the environment variables in handy -2. Set the environment variables in your app so that embedchain has context about it. -3. Just use embedchain and everything will be logged to LangSmith, so that you can better test and monitor your application. - -Let's cover each step in detail. - - -* First make sure that you have created a LangSmith account and have all the necessary variables handy. LangSmith has a [good documentation](https://docs.smith.langchain.com/) on how to get started with their service. - -* Once you have setup the account, we will need the following environment variables - -```bash -# Setting environment variable for LangChain Tracing V2 integration. -export LANGCHAIN_TRACING_V2=true - -# Setting the API endpoint for LangChain. -export LANGCHAIN_ENDPOINT=https://api.smith.langchain.com - -# Replace '' with your LangChain API key. -export LANGCHAIN_API_KEY= - -# Replace '' with your LangChain project name, or it defaults to "default". -export LANGCHAIN_PROJECT= # if not specified, defaults to "default" -``` - -If you are using Python, you can use the following code to set environment variables - -```python -import os - -# Setting environment variable for LangChain Tracing V2 integration. -os.environ['LANGCHAIN_TRACING_V2'] = 'true' - -# Setting the API endpoint for LangChain. -os.environ['LANGCHAIN_ENDPOINT'] = 'https://api.smith.langchain.com' - -# Replace '' with your LangChain API key. -os.environ['LANGCHAIN_API_KEY'] = '' - -# Replace '' with your LangChain project name. -os.environ['LANGCHAIN_PROJECT'] = '' -``` - -* Now create an app using Embedchain and everything will be automatically visible in the LangSmith - - -```python -from embedchain import App - -# Initialize EmbedChain application. -app = App() - -# Add data to your app -app.add("https://en.wikipedia.org/wiki/Elon_Musk") - -# Query your app -app.query("How many companies did Elon found?") -``` - -* Now the entire log for this will be visible in langsmith. - - diff --git a/embedchain/docs/integration/openlit.mdx b/embedchain/docs/integration/openlit.mdx deleted file mode 100644 index 22036919e..000000000 --- a/embedchain/docs/integration/openlit.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: '🔭 OpenLIT' -description: 'OpenTelemetry-native Observability and Evals for LLMs & GPUs' ---- - -Embedchain now supports integration with [OpenLIT](https://github.com/openlit/openlit). - -## Getting Started - -### 1. Set environment variables -```bash -# Setting environment variable for OpenTelemetry destination and authetication. -export OTEL_EXPORTER_OTLP_ENDPOINT = "YOUR_OTEL_ENDPOINT" -export OTEL_EXPORTER_OTLP_HEADERS = "YOUR_OTEL_ENDPOINT_AUTH" -``` - -### 2. Install the OpenLIT SDK -Open your terminal and run: - -```shell -pip install openlit -``` - -### 3. Setup Your Application for Monitoring -Now create an app using Embedchain and initialize OpenTelemetry monitoring - -```python -from embedchain import App -import OpenLIT - -# Initialize OpenLIT Auto Instrumentation for monitoring. -openlit.init() - -# Initialize EmbedChain application. -app = App() - -# Add data to your app -app.add("https://en.wikipedia.org/wiki/Elon_Musk") - -# Query your app -app.query("How many companies did Elon found?") -``` - -### 4. Visualize - -Once you've set up data collection with OpenLIT, you can visualize and analyze this information to better understand your application's performance: - -- **Using OpenLIT UI:** Connect to OpenLIT's UI to start exploring performance metrics. Visit the OpenLIT [Quickstart Guide](https://docs.openlit.io/latest/quickstart) for step-by-step details. - -- **Integrate with existing Observability Tools:** If you use tools like Grafana or DataDog, you can integrate the data collected by OpenLIT. For instructions on setting up these connections, check the OpenLIT [Connections Guide](https://docs.openlit.io/latest/connections/intro). diff --git a/embedchain/docs/integration/streamlit-mistral.mdx b/embedchain/docs/integration/streamlit-mistral.mdx deleted file mode 100644 index d7b795755..000000000 --- a/embedchain/docs/integration/streamlit-mistral.mdx +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: '🚀 Streamlit' -description: 'Integrate with Streamlit to plug and play with any LLM' ---- - -In this example, we will learn how to use `mistralai/Mixtral-8x7B-Instruct-v0.1` and Embedchain together with Streamlit to build a simple RAG chatbot. - -![Streamlit + Embedchain Demo](https://github.com/embedchain/embedchain/assets/73601258/052f7378-797c-41cf-ac81-f004d0d44dd1) - -## Setup - -Install Embedchain and Streamlit. -```bash -pip install embedchain streamlit -``` - - - ```python - import os - from embedchain import App - import streamlit as st - - with st.sidebar: - huggingface_access_token = st.text_input("Hugging face Token", key="chatbot_api_key", type="password") - "[Get Hugging Face Access Token](https://huggingface.co/settings/tokens)" - "[View the source code](https://github.com/embedchain/examples/mistral-streamlit)" - - - st.title("💬 Chatbot") - st.caption("🚀 An Embedchain app powered by Mistral!") - if "messages" not in st.session_state: - st.session_state.messages = [ - { - "role": "assistant", - "content": """ - Hi! I'm a chatbot. I can answer questions and learn new things!\n - Ask me anything and if you want me to learn something do `/add `.\n - I can learn mostly everything. :) - """, - } - ] - - for message in st.session_state.messages: - with st.chat_message(message["role"]): - st.markdown(message["content"]) - - if prompt := st.chat_input("Ask me anything!"): - if not st.session_state.chatbot_api_key: - st.error("Please enter your Hugging Face Access Token") - st.stop() - - os.environ["HUGGINGFACE_ACCESS_TOKEN"] = st.session_state.chatbot_api_key - app = App.from_config(config_path="config.yaml") - - if prompt.startswith("/add"): - with st.chat_message("user"): - st.markdown(prompt) - st.session_state.messages.append({"role": "user", "content": prompt}) - prompt = prompt.replace("/add", "").strip() - with st.chat_message("assistant"): - message_placeholder = st.empty() - message_placeholder.markdown("Adding to knowledge base...") - app.add(prompt) - message_placeholder.markdown(f"Added {prompt} to knowledge base!") - st.session_state.messages.append({"role": "assistant", "content": f"Added {prompt} to knowledge base!"}) - st.stop() - - with st.chat_message("user"): - st.markdown(prompt) - st.session_state.messages.append({"role": "user", "content": prompt}) - - with st.chat_message("assistant"): - msg_placeholder = st.empty() - msg_placeholder.markdown("Thinking...") - full_response = "" - - for response in app.chat(prompt): - msg_placeholder.empty() - full_response += response - - msg_placeholder.markdown(full_response) - st.session_state.messages.append({"role": "assistant", "content": full_response}) - ``` - - - ```yaml - app: - config: - name: 'mistral-streamlit-app' - - llm: - provider: huggingface - config: - model: 'mistralai/Mixtral-8x7B-Instruct-v0.1' - temperature: 0.1 - max_tokens: 250 - top_p: 0.1 - stream: true - - embedder: - provider: huggingface - config: - model: 'sentence-transformers/all-mpnet-base-v2' - ``` - - - -## To run it locally, - -```bash -streamlit run app.py -``` diff --git a/embedchain/docs/logo/dark-rt.svg b/embedchain/docs/logo/dark-rt.svg deleted file mode 100644 index 83eb7fc69..000000000 --- a/embedchain/docs/logo/dark-rt.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/embedchain/docs/logo/dark.svg b/embedchain/docs/logo/dark.svg deleted file mode 100644 index cbd502094..000000000 --- a/embedchain/docs/logo/dark.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/embedchain/docs/logo/light-rt.svg b/embedchain/docs/logo/light-rt.svg deleted file mode 100644 index f204d17e6..000000000 --- a/embedchain/docs/logo/light-rt.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/embedchain/docs/logo/light.svg b/embedchain/docs/logo/light.svg deleted file mode 100644 index cbd502094..000000000 --- a/embedchain/docs/logo/light.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/embedchain/docs/mint.json b/embedchain/docs/mint.json deleted file mode 100644 index a3d4aec8d..000000000 --- a/embedchain/docs/mint.json +++ /dev/null @@ -1,277 +0,0 @@ -{ - "$schema": "https://mintlify.com/schema.json", - "name": "Embedchain", - "logo": { - "dark": "/logo/dark-rt.svg", - "light": "/logo/light-rt.svg", - "href": "https://github.com/embedchain/embedchain" - }, - "favicon": "/favicon.png", - "colors": { - "primary": "#3B2FC9", - "light": "#6673FF", - "dark": "#3B2FC9", - "background": { - "dark": "#0f1117", - "light": "#fff" - } - }, - "modeToggle": { - "default": "dark" - }, - "openapi": ["/rest-api.json"], - "metadata": { - "og:image": "/images/og.png", - "twitter:site": "@embedchain" - }, - "tabs": [ - { - "name": "Examples", - "url": "examples" - }, - { - "name": "API Reference", - "url": "api-reference" - } - ], - "anchors": [ - { - "name": "Talk to founders", - "icon": "calendar", - "url": "https://cal.com/taranjeetio/ec" - } - ], - "topbarLinks": [ - { - "name": "GitHub", - "url": "https://github.com/embedchain/embedchain" - } - ], - "topbarCtaButton": { - "name": "Join our slack", - "url": "https://embedchain.ai/slack" - }, - "primaryTab": { - "name": "📘 Documentation" - }, - "navigation": [ - { - "group": "Get Started", - "pages": [ - "get-started/quickstart", - "get-started/introduction", - "get-started/faq", - "get-started/full-stack", - { - "group": "🔗 Integrations", - "pages": [ - "integration/langsmith", - "integration/chainlit", - "integration/streamlit-mistral", - "integration/openlit", - "integration/helicone" - ] - } - ] - }, - { - "group": "Use cases", - "pages": [ - "use-cases/introduction", - "use-cases/chatbots", - "use-cases/question-answering", - "use-cases/semantic-search" - ] - }, - { - "group": "Components", - "pages": [ - "components/introduction", - { - "group": "🗂️ Data sources", - "pages": [ - "components/data-sources/overview", - { - "group": "Data types", - "pages": [ - "components/data-sources/pdf-file", - "components/data-sources/csv", - "components/data-sources/json", - "components/data-sources/text", - "components/data-sources/directory", - "components/data-sources/web-page", - "components/data-sources/youtube-channel", - "components/data-sources/youtube-video", - "components/data-sources/docs-site", - "components/data-sources/mdx", - "components/data-sources/docx", - "components/data-sources/notion", - "components/data-sources/sitemap", - "components/data-sources/xml", - "components/data-sources/qna", - "components/data-sources/openapi", - "components/data-sources/gmail", - "components/data-sources/github", - "components/data-sources/postgres", - "components/data-sources/mysql", - "components/data-sources/slack", - "components/data-sources/discord", - "components/data-sources/discourse", - "components/data-sources/substack", - "components/data-sources/beehiiv", - "components/data-sources/directory", - "components/data-sources/dropbox", - "components/data-sources/image", - "components/data-sources/audio", - "components/data-sources/custom" - ] - }, - "components/data-sources/data-type-handling" - ] - }, - { - "group": "🗄️ Vector databases", - "pages": [ - "components/vector-databases/chromadb", - "components/vector-databases/elasticsearch", - "components/vector-databases/pinecone", - "components/vector-databases/opensearch", - "components/vector-databases/qdrant", - "components/vector-databases/weaviate", - "components/vector-databases/zilliz" - ] - }, - "components/llms", - "components/embedding-models", - "components/evaluation" - ] - }, - { - "group": "Deployment", - "pages": [ - "get-started/deployment", - "deployment/fly_io", - "deployment/modal_com", - "deployment/render_com", - "deployment/railway", - "deployment/streamlit_io", - "deployment/gradio_app", - "deployment/huggingface_spaces" - ] - }, - { - "group": "Community", - "pages": ["community/connect-with-us"] - }, - { - "group": "Examples", - "pages": [ - "examples/chat-with-PDF", - "examples/notebooks-and-replits", - { - "group": "REST API Service", - "pages": [ - "examples/rest-api/getting-started", - "examples/rest-api/create", - "examples/rest-api/get-all-apps", - "examples/rest-api/add-data", - "examples/rest-api/get-data", - "examples/rest-api/query", - "examples/rest-api/deploy", - "examples/rest-api/delete", - "examples/rest-api/check-status" - ] - }, - "examples/openai-assistant", - "examples/opensource-assistant", - "examples/nextjs-assistant", - "examples/slack-AI" - ] - }, - { - "group": "Chatbots", - "pages": [ - "examples/discord_bot", - "examples/slack_bot", - "examples/telegram_bot", - "examples/whatsapp_bot", - "examples/poe_bot" - ] - }, - { - "group": "Showcase", - "pages": ["examples/showcase"] - }, - { - "group": "API Reference", - "pages": [ - "api-reference/app/overview", - { - "group": "App methods", - "pages": [ - "api-reference/app/add", - "api-reference/app/query", - "api-reference/app/chat", - "api-reference/app/search", - "api-reference/app/get", - "api-reference/app/evaluate", - "api-reference/app/deploy", - "api-reference/app/reset", - "api-reference/app/delete" - ] - }, - "api-reference/store/openai-assistant", - "api-reference/store/ai-assistants", - "api-reference/advanced/configuration" - ] - }, - { - "group": "Contributing", - "pages": [ - "contribution/guidelines", - "contribution/dev", - "contribution/docs", - "contribution/python" - ] - }, - { - "group": "Product", - "pages": ["product/release-notes"] - } - ], - "footerSocials": { - "website": "https://embedchain.ai", - "github": "https://github.com/embedchain/embedchain", - "slack": "https://embedchain.ai/slack", - "discord": "https://discord.gg/6PzXDgEjG5", - "twitter": "https://twitter.com/embedchain", - "linkedin": "https://www.linkedin.com/company/embedchain" - }, - "isWhiteLabeled": true, - "analytics": { - "posthog": { - "apiKey": "phc_PHQDA5KwztijnSojsxJ2c1DuJd52QCzJzT2xnSGvjN2", - "apiHost": "https://app.embedchain.ai/ingest" - }, - "ga4": { - "measurementId": "G-4QK7FJE6T3" - } - }, - "feedback": { - "suggestEdit": true, - "raiseIssue": true, - "thumbsRating": true - }, - "search": { - "prompt": "✨ Search embedchain docs..." - }, - "api": { - "baseUrl": "http://localhost:8080" - }, - "redirects": [ - { - "source": "/changelog/command-line", - "destination": "/get-started/introduction" - } - ] -} diff --git a/embedchain/docs/product/release-notes.mdx b/embedchain/docs/product/release-notes.mdx deleted file mode 100644 index 02bcf977b..000000000 --- a/embedchain/docs/product/release-notes.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: ' 📜 Release Notes' -url: https://github.com/embedchain/embedchain/releases ---- \ No newline at end of file diff --git a/embedchain/docs/rest-api.json b/embedchain/docs/rest-api.json deleted file mode 100644 index 087d7e06c..000000000 --- a/embedchain/docs/rest-api.json +++ /dev/null @@ -1,427 +0,0 @@ -{ - "openapi": "3.1.0", - "info": { - "title": "Embedchain REST API", - "description": "This is the REST API for Embedchain.", - "license": { - "name": "Apache 2.0", - "url": "https://github.com/embedchain/embedchain/blob/main/LICENSE" - }, - "version": "0.0.1" - }, - "paths": { - "/ping": { - "get": { - "tags": ["Utility"], - "summary": "Check status", - "description": "Endpoint to check the status of the API", - "operationId": "check_status_ping_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { "application/json": { "schema": {} } } - } - } - } - }, - "/apps": { - "get": { - "tags": ["Apps"], - "summary": "Get all apps", - "description": "Get all applications", - "operationId": "get_all_apps_apps_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { "application/json": { "schema": {} } } - } - } - } - }, - "/create": { - "post": { - "tags": ["Apps"], - "summary": "Create app", - "description": "Create a new app using App ID", - "operationId": "create_app_using_default_config_create_post", - "parameters": [ - { - "name": "app_id", - "in": "query", - "required": true, - "schema": { "type": "string", "title": "App Id" } - } - ], - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/Body_create_app_using_default_config_create_post" - } - ], - "title": "Body" - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DefaultResponse" } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/HTTPValidationError" } - } - } - } - } - } - }, - "/{app_id}/data": { - "get": { - "tags": ["Apps"], - "summary": "Get data", - "description": "Get all data sources for an app", - "operationId": "get_datasources_associated_with_app_id__app_id__data_get", - "parameters": [ - { - "name": "app_id", - "in": "path", - "required": true, - "schema": { "type": "string", "title": "App Id" } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { "application/json": { "schema": {} } } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/HTTPValidationError" } - } - } - } - } - } - }, - "/{app_id}/add": { - "post": { - "tags": ["Apps"], - "summary": "Add data", - "description": "Add a data source to an app.", - "operationId": "add_datasource_to_an_app__app_id__add_post", - "parameters": [ - { - "name": "app_id", - "in": "path", - "required": true, - "schema": { "type": "string", "title": "App Id" } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/SourceApp" } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DefaultResponse" } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/HTTPValidationError" } - } - } - } - } - } - }, - "/{app_id}/query": { - "post": { - "tags": ["Apps"], - "summary": "Query app", - "description": "Query an app", - "operationId": "query_an_app__app_id__query_post", - "parameters": [ - { - "name": "app_id", - "in": "path", - "required": true, - "schema": { "type": "string", "title": "App Id" } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/QueryApp" } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DefaultResponse" } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/HTTPValidationError" } - } - } - } - } - } - }, - "/{app_id}/chat": { - "post": { - "tags": ["Apps"], - "summary": "Chat", - "description": "Chat with an app.\n\napp_id: The ID of the app. Use \"default\" for the default app.\n\nmessage: The message that you want to send to the app.", - "operationId": "chat_with_an_app__app_id__chat_post", - "parameters": [ - { - "name": "app_id", - "in": "path", - "required": true, - "schema": { "type": "string", "title": "App Id" } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/MessageApp" } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DefaultResponse" } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/HTTPValidationError" } - } - } - } - } - } - }, - "/{app_id}/deploy": { - "post": { - "tags": ["Apps"], - "summary": "Deploy app", - "description": "Deploy an existing app.", - "operationId": "deploy_app__app_id__deploy_post", - "parameters": [ - { - "name": "app_id", - "in": "path", - "required": true, - "schema": { "type": "string", "title": "App Id" } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DeployAppRequest" } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DefaultResponse" } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/HTTPValidationError" } - } - } - } - } - } - }, - "/{app_id}/delete": { - "delete": { - "tags": ["Apps"], - "summary": "Delete app", - "description": "Delete an existing app", - "operationId": "delete_app__app_id__delete_delete", - "parameters": [ - { - "name": "app_id", - "in": "path", - "required": true, - "schema": { "type": "string", "title": "App Id" } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DefaultResponse" } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/HTTPValidationError" } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "Body_create_app_using_default_config_create_post": { - "properties": { - "config": { "type": "string", "format": "binary", "title": "Config" } - }, - "type": "object", - "title": "Body_create_app_using_default_config_create_post" - }, - "DefaultResponse": { - "properties": { "response": { "type": "string", "title": "Response" } }, - "type": "object", - "required": ["response"], - "title": "DefaultResponse" - }, - "DeployAppRequest": { - "properties": { - "api_key": { - "type": "string", - "title": "Api Key", - "description": "The Embedchain API key for app deployments. You get the api key on the Embedchain platform by visiting [https://app.embedchain.ai](https://app.embedchain.ai)", - "default": "" - } - }, - "type": "object", - "title": "DeployAppRequest", - "example":{ - "api_key":"ec-xxx" - } - }, - "HTTPValidationError": { - "properties": { - "detail": { - "items": { "$ref": "#/components/schemas/ValidationError" }, - "type": "array", - "title": "Detail" - } - }, - "type": "object", - "title": "HTTPValidationError" - }, - "MessageApp": { - "properties": { - "message": { - "type": "string", - "title": "Message", - "description": "The message that you want to send to the App.", - "default": "" - } - }, - "type": "object", - "title": "MessageApp" - }, - "QueryApp": { - "properties": { - "query": { - "type": "string", - "title": "Query", - "description": "The query that you want to ask the App.", - "default": "" - } - }, - "type": "object", - "title": "QueryApp", - "example":{ - "query":"Who is Elon Musk?" - } - }, - "SourceApp": { - "properties": { - "source": { - "type": "string", - "title": "Source", - "description": "The source that you want to add to the App.", - "default": "" - }, - "data_type": { - "anyOf": [{ "type": "string" }, { "type": "null" }], - "title": "Data Type", - "description": "The type of data to add, remove it if you want Embedchain to detect it automatically.", - "default": "" - } - }, - "type": "object", - "title": "SourceApp", - "example":{ - "source":"https://en.wikipedia.org/wiki/Elon_Musk" - } - }, - "ValidationError": { - "properties": { - "loc": { - "items": { "anyOf": [{ "type": "string" }, { "type": "integer" }] }, - "type": "array", - "title": "Location" - }, - "msg": { "type": "string", "title": "Message" }, - "type": { "type": "string", "title": "Error Type" } - }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError" - } - } - } - } diff --git a/embedchain/docs/support/get-help.mdx b/embedchain/docs/support/get-help.mdx deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/docs/use-cases/chatbots.mdx b/embedchain/docs/use-cases/chatbots.mdx deleted file mode 100644 index d11e45257..000000000 --- a/embedchain/docs/use-cases/chatbots.mdx +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: '🤖 Chatbots' ---- - -Chatbots, especially those powered by Large Language Models (LLMs), have a wide range of use cases, significantly enhancing various aspects of business, education, and personal assistance. Here are some key applications: - -- **Customer Service**: Automating responses to common queries and providing 24/7 support. -- **Education**: Offering personalized tutoring and learning assistance. -- **E-commerce**: Assisting in product discovery, recommendations, and transactions. -- **Content Management**: Aiding in writing, summarizing, and organizing content. -- **Data Analysis**: Extracting insights from large datasets. -- **Language Translation**: Providing real-time multilingual support. -- **Mental Health**: Offering preliminary mental health support and conversation. -- **Entertainment**: Engaging users with games, quizzes, and humorous chats. -- **Accessibility Aid**: Enhancing information and service access for individuals with disabilities. - -Embedchain provides the right set of tools to create chatbots for the above use cases. Refer to the following examples of chatbots on and you can built on top of these examples: - - - - Build a tailored GPT chatbot suited for your specific needs. - - - Enhance your Slack workspace with a specialized bot. - - - Create an engaging bot for your Discord server. - - - Develop a handy assistant for Telegram users. - - - Design a WhatsApp bot for efficient communication. - - - Explore advanced bot interactions with Poe Bot. - - diff --git a/embedchain/docs/use-cases/introduction.mdx b/embedchain/docs/use-cases/introduction.mdx deleted file mode 100644 index e908ba64d..000000000 --- a/embedchain/docs/use-cases/introduction.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: 🧱 Introduction ---- - -## Overview - -You can use embedchain to create the following usecases: - -* [Chatbots](/use-cases/chatbots) -* [Question Answering](/use-cases/question-answering) -* [Semantic Search](/use-cases/semantic-search) \ No newline at end of file diff --git a/embedchain/docs/use-cases/question-answering.mdx b/embedchain/docs/use-cases/question-answering.mdx deleted file mode 100644 index f538419b5..000000000 --- a/embedchain/docs/use-cases/question-answering.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: '❓ Question Answering' ---- - -Utilizing large language models (LLMs) for question answering is a transformative application, bringing significant benefits to various real-world situations. Embedchain extensively supports tasks related to question answering, including summarization, content creation, language translation, and data analysis. The versatility of question answering with LLMs enables solutions for numerous practical applications such as: - -- **Educational Aid**: Enhancing learning experiences and aiding with homework -- **Customer Support**: Addressing and resolving customer queries efficiently -- **Research Assistance**: Facilitating academic and professional research endeavors -- **Healthcare Information**: Providing fundamental medical knowledge -- **Technical Support**: Resolving technology-related inquiries -- **Legal Information**: Offering basic legal advice and information -- **Business Insights**: Delivering market analysis and strategic business advice -- **Language Learning** Assistance: Aiding in understanding and translating languages -- **Travel Guidance**: Supplying information on travel and hospitality -- **Content Development**: Assisting authors and creators with research and idea generation - -## Example: Build a Q&A System with Embedchain for Next.JS - -Quickly create a RAG pipeline to answer queries about the [Next.JS Framework](https://nextjs.org/) using Embedchain tools. - -### Step 1: Set Up Your RAG Pipeline - -First, let's create your RAG pipeline. Open your Python environment and enter: - -```python Create pipeline -from embedchain import App -app = App() -``` - -This initializes your application. - -### Step 2: Populate Your Pipeline with Data - -Now, let's add data to your pipeline. We'll include the Next.JS website and its documentation: - -```python Ingest data sources -# Add Next.JS Website and docs -app.add("https://nextjs.org/sitemap.xml", data_type="sitemap") - -# Add Next.JS Forum data -app.add("https://nextjs-forum.com/sitemap.xml", data_type="sitemap") -``` - -This step incorporates over **15K pages** from the Next.JS website and forum into your pipeline. For more data source options, check the [Embedchain data sources overview](/components/data-sources/overview). - -### Step 3: Local Testing of Your Pipeline - -Test the pipeline on your local machine: - -```python Query App -app.query("Summarize the features of Next.js 14?") -``` - -Run this query to see how your pipeline responds with information about Next.js 14. - -### (Optional) Step 4: Deploying Your RAG Pipeline - -Want to go live? Deploy your pipeline with these options: - -- Deploy on the Embedchain Platform -- Self-host on your preferred cloud provider - -For detailed deployment instructions, follow these guides: - -- [Deploying on Embedchain Platform](/get-started/deployment#deploy-on-embedchain-platform) -- [Self-hosting Guide](/get-started/deployment#self-hosting) - -## Need help? - -If you are looking to configure the RAG pipeline further, feel free to checkout the [API reference](/api-reference/pipeline/query). - -In case you run into issues, feel free to contact us via any of the following methods: - - diff --git a/embedchain/docs/use-cases/semantic-search.mdx b/embedchain/docs/use-cases/semantic-search.mdx deleted file mode 100644 index f506e5dd1..000000000 --- a/embedchain/docs/use-cases/semantic-search.mdx +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: '🔍 Semantic Search' ---- - -Semantic searching, which involves understanding the intent and contextual meaning behind search queries, is yet another popular use-case of RAG. It has several popular use cases across various domains: - -- **Information Retrieval**: Enhances search accuracy in databases and websites -- **E-commerce**: Improves product discovery in online shopping -- **Customer Support**: Powers smarter chatbots for effective responses -- **Content Discovery**: Aids in finding relevant media content -- **Knowledge Management**: Streamlines document and data retrieval in enterprises -- **Healthcare**: Facilitates medical research and literature search -- **Legal Research**: Assists in legal document and case law search -- **Academic Research**: Aids in academic paper discovery -- **Language Processing**: Enables multilingual search capabilities - -Embedchain offers a simple yet customizable `search()` API that you can use for semantic search. See the example in the next section to know more. - -## Example: Semantic Search over Next.JS Website + Forum - -### Step 1: Set Up Your RAG Pipeline - -First, let's create your RAG pipeline. Open your Python environment and enter: - -```python Create pipeline -from embedchain import App -app = App() -``` - -This initializes your application. - -### Step 2: Populate Your Pipeline with Data - -Now, let's add data to your pipeline. We'll include the Next.JS website and its documentation: - -```python Ingest data sources -# Add Next.JS Website and docs -app.add("https://nextjs.org/sitemap.xml", data_type="sitemap") - -# Add Next.JS Forum data -app.add("https://nextjs-forum.com/sitemap.xml", data_type="sitemap") -``` - -This step incorporates over **15K pages** from the Next.JS website and forum into your pipeline. For more data source options, check the [Embedchain data sources overview](/components/data-sources/overview). - -### Step 3: Local Testing of Your Pipeline - -Test the pipeline on your local machine: - -```python Search App -app.search("Summarize the features of Next.js 14?") -[ - { - 'context': 'Next.js 14 | Next.jsBack to BlogThursday, October 26th 2023Next.js 14Posted byLee Robinson@leeerobTim Neutkens@timneutkensAs we announced at Next.js Conf, Next.js 14 is our most focused release with: Turbopack: 5,000 tests passing for App & Pages Router 53% faster local server startup 94% faster code updates with Fast Refresh Server Actions (Stable): Progressively enhanced mutations Integrated with caching & revalidating Simple function calls, or works natively with forms Partial Prerendering', - 'metadata': { - 'source': 'https://nextjs.org/blog/next-14', - 'document_id': '6c8d1a7b-ea34-4927-8823-daa29dcfc5af--b83edb69b8fc7e442ff8ca311b48510e6c80bf00caa806b3a6acb34e1bcdd5d5' - } - }, - { - 'context': 'Next.js 13.3 | Next.jsBack to BlogThursday, April 6th 2023Next.js 13.3Posted byDelba de Oliveira@delba_oliveiraTim Neutkens@timneutkensNext.js 13.3 adds popular community-requested features, including: File-Based Metadata API: Dynamically generate sitemaps, robots, favicons, and more. Dynamic Open Graph Images: Generate OG images using JSX, HTML, and CSS. Static Export for App Router: Static / Single-Page Application (SPA) support for Server Components. Parallel Routes and Interception: Advanced', - 'metadata': { - 'source': 'https://nextjs.org/blog/next-13-3', - 'document_id': '6c8d1a7b-ea34-4927-8823-daa29dcfc5af--b83edb69b8fc7e442ff8ca311b48510e6c80bf00caa806b3a6acb34e1bcdd5d5' - } - }, - { - 'context': 'Upgrading: Version 14 | Next.js MenuUsing App RouterFeatures available in /appApp Router.UpgradingVersion 14Version 14 Upgrading from 13 to 14 To update to Next.js version 14, run the following command using your preferred package manager: Terminalnpm i next@latest react@latest react-dom@latest eslint-config-next@latest Terminalyarn add next@latest react@latest react-dom@latest eslint-config-next@latest Terminalpnpm up next react react-dom eslint-config-next -latest Terminalbun add next@latest', - 'metadata': { - 'source': 'https://nextjs.org/docs/app/building-your-application/upgrading/version-14', - 'document_id': '6c8d1a7b-ea34-4927-8823-daa29dcfc5af--b83edb69b8fc7e442ff8ca311b48510e6c80bf00caa806b3a6acb34e1bcdd5d5' - } - } -] -``` -The `source` key contains the url of the document that yielded that document chunk. - -If you are interested in configuring the search further, refer to our [API documentation](/api-reference/pipeline/search). - -### (Optional) Step 4: Deploying Your RAG Pipeline - -Want to go live? Deploy your pipeline with these options: - -- Deploy on the Embedchain Platform -- Self-host on your preferred cloud provider - -For detailed deployment instructions, follow these guides: - -- [Deploying on Embedchain Platform](/get-started/deployment#deploy-on-embedchain-platform) -- [Self-hosting Guide](/get-started/deployment#self-hosting) - ----- - -This guide will help you swiftly set up a semantic search pipeline with Embedchain, making it easier to access and analyze specific information from large data sources. - - -## Need help? - -In case you run into issues, feel free to contact us via any of the following methods: - - diff --git a/embedchain/embedchain/__init__.py b/embedchain/embedchain/__init__.py deleted file mode 100644 index b59aed77d..000000000 --- a/embedchain/embedchain/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -import importlib.metadata - -__version__ = importlib.metadata.version(__package__ or __name__) - -from embedchain.app import App # noqa: F401 -from embedchain.client import Client # noqa: F401 -from embedchain.pipeline import Pipeline # noqa: F401 - -# Setup the user directory if doesn't exist already -Client.setup() diff --git a/embedchain/embedchain/alembic.ini b/embedchain/embedchain/alembic.ini deleted file mode 100644 index 53023ad8d..000000000 --- a/embedchain/embedchain/alembic.ini +++ /dev/null @@ -1,116 +0,0 @@ -# A generic, single database configuration. - -[alembic] -# path to migration scripts -script_location = embedchain:migrations - -# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s -# Uncomment the line below if you want the files to be prepended with date and time -# see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file -# for all available tokens -# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s - -# sys.path path, will be prepended to sys.path if present. -# defaults to the current working directory. -prepend_sys_path = . - -# timezone to use when rendering the date within the migration file -# as well as the filename. -# If specified, requires the python>=3.9 or backports.zoneinfo library. -# Any required deps can installed by adding `alembic[tz]` to the pip requirements -# string value is passed to ZoneInfo() -# leave blank for localtime -# timezone = - -# max length of characters to apply to the -# "slug" field -# truncate_slug_length = 40 - -# set to 'true' to run the environment during -# the 'revision' command, regardless of autogenerate -# revision_environment = false - -# set to 'true' to allow .pyc and .pyo files without -# a source .py file to be detected as revisions in the -# versions/ directory -# sourceless = false - -# version location specification; This defaults -# to alembic/versions. When using multiple version -# directories, initial revisions must be specified with --version-path. -# The path separator used here should be the separator specified by "version_path_separator" below. -# version_locations = %(here)s/bar:%(here)s/bat:alembic/versions - -# version path separator; As mentioned above, this is the character used to split -# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep. -# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas. -# Valid values for version_path_separator are: -# -# version_path_separator = : -# version_path_separator = ; -# version_path_separator = space -version_path_separator = os # Use os.pathsep. Default configuration used for new projects. - -# set to 'true' to search source files recursively -# in each "version_locations" directory -# new in Alembic version 1.10 -# recursive_version_locations = false - -# the output encoding used when revision files -# are written from script.py.mako -# output_encoding = utf-8 - -sqlalchemy.url = driver://user:pass@localhost/dbname - - -[post_write_hooks] -# post_write_hooks defines scripts or Python functions that are run -# on newly generated revision scripts. See the documentation for further -# detail and examples - -# format using "black" - use the console_scripts runner, against the "black" entrypoint -# hooks = black -# black.type = console_scripts -# black.entrypoint = black -# black.options = -l 79 REVISION_SCRIPT_FILENAME - -# lint with attempts to fix using "ruff" - use the exec runner, execute a binary -# hooks = ruff -# ruff.type = exec -# ruff.executable = %(here)s/.venv/bin/ruff -# ruff.options = --fix REVISION_SCRIPT_FILENAME - -# Logging configuration -[loggers] -keys = root,sqlalchemy,alembic - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = WARN -handlers = console -qualname = - -[logger_sqlalchemy] -level = WARN -handlers = -qualname = sqlalchemy.engine - -[logger_alembic] -level = WARN -handlers = -qualname = alembic - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(levelname)-5.5s [%(name)s] %(message)s -datefmt = %H:%M:%S diff --git a/embedchain/embedchain/app.py b/embedchain/embedchain/app.py deleted file mode 100644 index b4d051607..000000000 --- a/embedchain/embedchain/app.py +++ /dev/null @@ -1,517 +0,0 @@ -import ast -import concurrent.futures -import json -import logging -import os -from typing import Any, Optional, Union - -import requests -import yaml -from tqdm import tqdm - -from embedchain.cache import ( - Config, - ExactMatchEvaluation, - SearchDistanceEvaluation, - cache, - gptcache_data_manager, - gptcache_pre_function, -) -from embedchain.client import Client -from embedchain.config import AppConfig, CacheConfig, ChunkerConfig, Mem0Config -from embedchain.core.db.database import get_session -from embedchain.core.db.models import DataSource -from embedchain.embedchain import EmbedChain -from embedchain.embedder.base import BaseEmbedder -from embedchain.embedder.openai import OpenAIEmbedder -from embedchain.evaluation.base import BaseMetric -from embedchain.evaluation.metrics import ( - AnswerRelevance, - ContextRelevance, - Groundedness, -) -from embedchain.factory import EmbedderFactory, LlmFactory, VectorDBFactory -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm -from embedchain.llm.openai import OpenAILlm -from embedchain.telemetry.posthog import AnonymousTelemetry -from embedchain.utils.evaluation import EvalData, EvalMetric -from embedchain.utils.misc import validate_config -from embedchain.vectordb.base import BaseVectorDB -from embedchain.vectordb.chroma import ChromaDB -from mem0 import Memory - -logger = logging.getLogger(__name__) - - -@register_deserializable -class App(EmbedChain): - """ - EmbedChain App lets you create a LLM powered app for your unstructured - data by defining your chosen data source, embedding model, - and vector database. - """ - - def __init__( - self, - id: str = None, - name: str = None, - config: AppConfig = None, - db: BaseVectorDB = None, - embedding_model: BaseEmbedder = None, - llm: BaseLlm = None, - config_data: dict = None, - auto_deploy: bool = False, - chunker: ChunkerConfig = None, - cache_config: CacheConfig = None, - memory_config: Mem0Config = None, - log_level: int = logging.WARN, - ): - """ - Initialize a new `App` instance. - - :param config: Configuration for the pipeline, defaults to None - :type config: AppConfig, optional - :param db: The database to use for storing and retrieving embeddings, defaults to None - :type db: BaseVectorDB, optional - :param embedding_model: The embedding model used to calculate embeddings, defaults to None - :type embedding_model: BaseEmbedder, optional - :param llm: The LLM model used to calculate embeddings, defaults to None - :type llm: BaseLlm, optional - :param config_data: Config dictionary, defaults to None - :type config_data: dict, optional - :param auto_deploy: Whether to deploy the pipeline automatically, defaults to False - :type auto_deploy: bool, optional - :raises Exception: If an error occurs while creating the pipeline - """ - if id and config_data: - raise Exception("Cannot provide both id and config. Please provide only one of them.") - - if id and name: - raise Exception("Cannot provide both id and name. Please provide only one of them.") - - if name and config: - raise Exception("Cannot provide both name and config. Please provide only one of them.") - - self.auto_deploy = auto_deploy - # Store the dict config as an attribute to be able to send it - self.config_data = config_data if (config_data and validate_config(config_data)) else None - self.client = None - # pipeline_id from the backend - self.id = None - self.chunker = ChunkerConfig(**chunker) if chunker else None - self.cache_config = cache_config - self.memory_config = memory_config - - self.config = config or AppConfig() - self.name = self.config.name - self.config.id = self.local_id = "default-app-id" if self.config.id is None else self.config.id - - if id is not None: - # Init client first since user is trying to fetch the pipeline - # details from the platform - self._init_client() - pipeline_details = self._get_pipeline(id) - self.config.id = self.local_id = pipeline_details["metadata"]["local_id"] - self.id = id - - if name is not None: - self.name = name - - self.embedding_model = embedding_model or OpenAIEmbedder() - self.db = db or ChromaDB() - self.llm = llm or OpenAILlm() - self._init_db() - - # Session for the metadata db - self.db_session = get_session() - - # If cache_config is provided, initializing the cache ... - if self.cache_config is not None: - self._init_cache() - - # If memory_config is provided, initializing the memory ... - self.mem0_memory = None - if self.memory_config is not None: - self.mem0_memory = Memory() - - # Send anonymous telemetry - self._telemetry_props = {"class": self.__class__.__name__} - self.telemetry = AnonymousTelemetry(enabled=self.config.collect_metrics) - self.telemetry.capture(event_name="init", properties=self._telemetry_props) - - self.user_asks = [] - if self.auto_deploy: - self.deploy() - - def _init_db(self): - """ - Initialize the database. - """ - self.db._set_embedder(self.embedding_model) - self.db._initialize() - self.db.set_collection_name(self.db.config.collection_name) - - def _init_cache(self): - if self.cache_config.similarity_eval_config.strategy == "exact": - similarity_eval_func = ExactMatchEvaluation() - else: - similarity_eval_func = SearchDistanceEvaluation( - max_distance=self.cache_config.similarity_eval_config.max_distance, - positive=self.cache_config.similarity_eval_config.positive, - ) - - cache.init( - pre_embedding_func=gptcache_pre_function, - embedding_func=self.embedding_model.to_embeddings, - data_manager=gptcache_data_manager(vector_dimension=self.embedding_model.vector_dimension), - similarity_evaluation=similarity_eval_func, - config=Config(**self.cache_config.init_config.as_dict()), - ) - - def _init_client(self): - """ - Initialize the client. - """ - config = Client.load_config() - if config.get("api_key"): - self.client = Client() - else: - api_key = input( - "🔑 Enter your Embedchain API key. You can find the API key at https://app.embedchain.ai/settings/keys/ \n" # noqa: E501 - ) - self.client = Client(api_key=api_key) - - def _get_pipeline(self, id): - """ - Get existing pipeline - """ - print("🛠️ Fetching pipeline details from the platform...") - url = f"{self.client.host}/api/v1/pipelines/{id}/cli/" - r = requests.get( - url, - headers={"Authorization": f"Token {self.client.api_key}"}, - ) - if r.status_code == 404: - raise Exception(f"❌ Pipeline with id {id} not found!") - - print( - f"🎉 Pipeline loaded successfully! Pipeline url: https://app.embedchain.ai/pipelines/{r.json()['id']}\n" # noqa: E501 - ) - return r.json() - - def _create_pipeline(self): - """ - Create a pipeline on the platform. - """ - print("🛠️ Creating pipeline on the platform...") - # self.config_data is a dict. Pass it inside the key 'yaml_config' to the backend - payload = { - "yaml_config": json.dumps(self.config_data), - "name": self.name, - "local_id": self.local_id, - } - url = f"{self.client.host}/api/v1/pipelines/cli/create/" - r = requests.post( - url, - json=payload, - headers={"Authorization": f"Token {self.client.api_key}"}, - ) - if r.status_code not in [200, 201]: - raise Exception(f"❌ Error occurred while creating pipeline. API response: {r.text}") - - if r.status_code == 200: - print( - f"🎉🎉🎉 Existing pipeline found! View your pipeline: https://app.embedchain.ai/pipelines/{r.json()['id']}\n" # noqa: E501 - ) # noqa: E501 - elif r.status_code == 201: - print( - f"🎉🎉🎉 Pipeline created successfully! View your pipeline: https://app.embedchain.ai/pipelines/{r.json()['id']}\n" # noqa: E501 - ) - return r.json() - - def _get_presigned_url(self, data_type, data_value): - payload = {"data_type": data_type, "data_value": data_value} - r = requests.post( - f"{self.client.host}/api/v1/pipelines/{self.id}/cli/presigned_url/", - json=payload, - headers={"Authorization": f"Token {self.client.api_key}"}, - ) - r.raise_for_status() - return r.json() - - def _upload_file_to_presigned_url(self, presigned_url, file_path): - try: - with open(file_path, "rb") as file: - response = requests.put(presigned_url, data=file) - response.raise_for_status() - return response.status_code == 200 - except Exception as e: - logger.exception(f"Error occurred during file upload: {str(e)}") - print("❌ Error occurred during file upload!") - return False - - def _upload_data_to_pipeline(self, data_type, data_value, metadata=None): - payload = { - "data_type": data_type, - "data_value": data_value, - "metadata": metadata, - } - try: - self._send_api_request(f"/api/v1/pipelines/{self.id}/cli/add/", payload) - # print the local file path if user tries to upload a local file - printed_value = metadata.get("file_path") if metadata.get("file_path") else data_value - print(f"✅ Data of type: {data_type}, value: {printed_value} added successfully.") - except Exception as e: - print(f"❌ Error occurred during data upload for type {data_type}!. Error: {str(e)}") - - def _send_api_request(self, endpoint, payload): - url = f"{self.client.host}{endpoint}" - headers = {"Authorization": f"Token {self.client.api_key}"} - response = requests.post(url, json=payload, headers=headers) - response.raise_for_status() - return response - - def _process_and_upload_data(self, data_hash, data_type, data_value): - if os.path.isabs(data_value): - presigned_url_data = self._get_presigned_url(data_type, data_value) - presigned_url = presigned_url_data["presigned_url"] - s3_key = presigned_url_data["s3_key"] - if self._upload_file_to_presigned_url(presigned_url, file_path=data_value): - metadata = {"file_path": data_value, "s3_key": s3_key} - data_value = presigned_url - else: - logger.error(f"File upload failed for hash: {data_hash}") - return False - else: - if data_type == "qna_pair": - data_value = list(ast.literal_eval(data_value)) - metadata = {} - - try: - self._upload_data_to_pipeline(data_type, data_value, metadata) - self._mark_data_as_uploaded(data_hash) - return True - except Exception: - print(f"❌ Error occurred during data upload for hash {data_hash}!") - return False - - def _mark_data_as_uploaded(self, data_hash): - self.db_session.query(DataSource).filter_by(hash=data_hash, app_id=self.local_id).update({"is_uploaded": 1}) - - def get_data_sources(self): - data_sources = self.db_session.query(DataSource).filter_by(app_id=self.local_id).all() - results = [] - for row in data_sources: - results.append({"data_type": row.type, "data_value": row.value, "metadata": row.meta_data}) - return results - - def deploy(self): - if self.client is None: - self._init_client() - - pipeline_data = self._create_pipeline() - self.id = pipeline_data["id"] - - results = self.db_session.query(DataSource).filter_by(app_id=self.local_id, is_uploaded=0).all() - if len(results) > 0: - print("🛠️ Adding data to your pipeline...") - for result in results: - data_hash, data_type, data_value = result.hash, result.data_type, result.data_value - self._process_and_upload_data(data_hash, data_type, data_value) - - # Send anonymous telemetry - self.telemetry.capture(event_name="deploy", properties=self._telemetry_props) - - @classmethod - def from_config( - cls, - config_path: Optional[str] = None, - config: Optional[dict[str, Any]] = None, - auto_deploy: bool = False, - yaml_path: Optional[str] = None, - ): - """ - Instantiate a App object from a configuration. - - :param config_path: Path to the YAML or JSON configuration file. - :type config_path: Optional[str] - :param config: A dictionary containing the configuration. - :type config: Optional[dict[str, Any]] - :param auto_deploy: Whether to deploy the app automatically, defaults to False - :type auto_deploy: bool, optional - :param yaml_path: (Deprecated) Path to the YAML configuration file. Use config_path instead. - :type yaml_path: Optional[str] - :return: An instance of the App class. - :rtype: App - """ - # Backward compatibility for yaml_path - if yaml_path and not config_path: - config_path = yaml_path - - if config_path and config: - raise ValueError("Please provide only one of config_path or config.") - - config_data = None - - if config_path: - file_extension = os.path.splitext(config_path)[1] - with open(config_path, "r", encoding="UTF-8") as file: - if file_extension in [".yaml", ".yml"]: - config_data = yaml.safe_load(file) - elif file_extension == ".json": - config_data = json.load(file) - else: - raise ValueError("config_path must be a path to a YAML or JSON file.") - elif config and isinstance(config, dict): - config_data = config - else: - logger.error( - "Please provide either a config file path (YAML or JSON) or a config dictionary. Falling back to defaults because no config is provided.", # noqa: E501 - ) - config_data = {} - - # Validate the config - validate_config(config_data) - - app_config_data = config_data.get("app", {}).get("config", {}) - vector_db_config_data = config_data.get("vectordb", {}) - embedding_model_config_data = config_data.get("embedding_model", config_data.get("embedder", {})) - memory_config_data = config_data.get("memory", {}) - llm_config_data = config_data.get("llm", {}) - chunker_config_data = config_data.get("chunker", {}) - cache_config_data = config_data.get("cache", None) - - app_config = AppConfig(**app_config_data) - memory_config = Mem0Config(**memory_config_data) if memory_config_data else None - - vector_db_provider = vector_db_config_data.get("provider", "chroma") - vector_db = VectorDBFactory.create(vector_db_provider, vector_db_config_data.get("config", {})) - - if llm_config_data: - llm_provider = llm_config_data.get("provider", "openai") - llm = LlmFactory.create(llm_provider, llm_config_data.get("config", {})) - else: - llm = None - - embedding_model_provider = embedding_model_config_data.get("provider", "openai") - embedding_model = EmbedderFactory.create( - embedding_model_provider, embedding_model_config_data.get("config", {}) - ) - - if cache_config_data is not None: - cache_config = CacheConfig.from_config(cache_config_data) - else: - cache_config = None - - return cls( - config=app_config, - llm=llm, - db=vector_db, - embedding_model=embedding_model, - config_data=config_data, - auto_deploy=auto_deploy, - chunker=chunker_config_data, - cache_config=cache_config, - memory_config=memory_config, - ) - - def _eval(self, dataset: list[EvalData], metric: Union[BaseMetric, str]): - """ - Evaluate the app on a dataset for a given metric. - """ - metric_str = metric.name if isinstance(metric, BaseMetric) else metric - eval_class_map = { - EvalMetric.CONTEXT_RELEVANCY.value: ContextRelevance, - EvalMetric.ANSWER_RELEVANCY.value: AnswerRelevance, - EvalMetric.GROUNDEDNESS.value: Groundedness, - } - - if metric_str in eval_class_map: - return eval_class_map[metric_str]().evaluate(dataset) - - # Handle the case for custom metrics - if isinstance(metric, BaseMetric): - return metric.evaluate(dataset) - else: - raise ValueError(f"Invalid metric: {metric}") - - def evaluate( - self, - questions: Union[str, list[str]], - metrics: Optional[list[Union[BaseMetric, str]]] = None, - num_workers: int = 4, - ): - """ - Evaluate the app on a question. - - param: questions: A question or a list of questions to evaluate. - type: questions: Union[str, list[str]] - param: metrics: A list of metrics to evaluate. Defaults to all metrics. - type: metrics: Optional[list[Union[BaseMetric, str]]] - param: num_workers: Number of workers to use for parallel processing. - type: num_workers: int - return: A dictionary containing the evaluation results. - rtype: dict - """ - if "OPENAI_API_KEY" not in os.environ: - raise ValueError("Please set the OPENAI_API_KEY environment variable with permission to use `gpt4` model.") - - queries, answers, contexts = [], [], [] - if isinstance(questions, list): - with concurrent.futures.ThreadPoolExecutor(max_workers=num_workers) as executor: - future_to_data = {executor.submit(self.query, q, citations=True): q for q in questions} - for future in tqdm( - concurrent.futures.as_completed(future_to_data), - total=len(future_to_data), - desc="Getting answer and contexts for questions", - ): - question = future_to_data[future] - queries.append(question) - answer, context = future.result() - answers.append(answer) - contexts.append(list(map(lambda x: x[0], context))) - else: - answer, context = self.query(questions, citations=True) - queries = [questions] - answers = [answer] - contexts = [list(map(lambda x: x[0], context))] - - metrics = metrics or [ - EvalMetric.CONTEXT_RELEVANCY.value, - EvalMetric.ANSWER_RELEVANCY.value, - EvalMetric.GROUNDEDNESS.value, - ] - - logger.info(f"Collecting data from {len(queries)} questions for evaluation...") - dataset = [] - for q, a, c in zip(queries, answers, contexts): - dataset.append(EvalData(question=q, answer=a, contexts=c)) - - logger.info(f"Evaluating {len(dataset)} data points...") - result = {} - with concurrent.futures.ThreadPoolExecutor(max_workers=num_workers) as executor: - future_to_metric = {executor.submit(self._eval, dataset, metric): metric for metric in metrics} - for future in tqdm( - concurrent.futures.as_completed(future_to_metric), - total=len(future_to_metric), - desc="Evaluating metrics", - ): - metric = future_to_metric[future] - if isinstance(metric, BaseMetric): - result[metric.name] = future.result() - else: - result[metric] = future.result() - - if self.config.collect_metrics: - telemetry_props = self._telemetry_props - metrics_names = [] - for metric in metrics: - if isinstance(metric, BaseMetric): - metrics_names.append(metric.name) - else: - metrics_names.append(metric) - telemetry_props["metrics"] = metrics_names - self.telemetry.capture(event_name="evaluate", properties=telemetry_props) - - return result diff --git a/embedchain/embedchain/bots/__init__.py b/embedchain/embedchain/bots/__init__.py deleted file mode 100644 index 34cef58f2..000000000 --- a/embedchain/embedchain/bots/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from embedchain.bots.poe import PoeBot # noqa: F401 -from embedchain.bots.whatsapp import WhatsAppBot # noqa: F401 - -# TODO: fix discord import -# from embedchain.bots.discord import DiscordBot diff --git a/embedchain/embedchain/bots/base.py b/embedchain/embedchain/bots/base.py deleted file mode 100644 index 4a817cc4c..000000000 --- a/embedchain/embedchain/bots/base.py +++ /dev/null @@ -1,48 +0,0 @@ -from typing import Any - -from embedchain import App -from embedchain.config import AddConfig, AppConfig, BaseLlmConfig -from embedchain.embedder.openai import OpenAIEmbedder -from embedchain.helpers.json_serializable import ( - JSONSerializable, - register_deserializable, -) -from embedchain.llm.openai import OpenAILlm -from embedchain.vectordb.chroma import ChromaDB - - -@register_deserializable -class BaseBot(JSONSerializable): - def __init__(self): - self.app = App(config=AppConfig(), llm=OpenAILlm(), db=ChromaDB(), embedding_model=OpenAIEmbedder()) - - def add(self, data: Any, config: AddConfig = None): - """ - Add data to the bot (to the vector database). - Auto-dectects type only, so some data types might not be usable. - - :param data: data to embed - :type data: Any - :param config: configuration class instance, defaults to None - :type config: AddConfig, optional - """ - config = config if config else AddConfig() - self.app.add(data, config=config) - - def query(self, query: str, config: BaseLlmConfig = None) -> str: - """ - Query the bot - - :param query: the user query - :type query: str - :param config: configuration class instance, defaults to None - :type config: BaseLlmConfig, optional - :return: Answer - :rtype: str - """ - config = config - return self.app.query(query, config=config) - - def start(self): - """Start the bot's functionality.""" - raise NotImplementedError("Subclasses must implement the start method.") diff --git a/embedchain/embedchain/bots/discord.py b/embedchain/embedchain/bots/discord.py deleted file mode 100644 index a288cab6d..000000000 --- a/embedchain/embedchain/bots/discord.py +++ /dev/null @@ -1,128 +0,0 @@ -import argparse -import logging -import os - -from embedchain.helpers.json_serializable import register_deserializable - -from .base import BaseBot - -try: - import discord - from discord import app_commands - from discord.ext import commands -except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for Discord are not installed." "Please install with `pip install discord==2.3.2`" - ) from None - - -logger = logging.getLogger(__name__) - -intents = discord.Intents.default() -intents.message_content = True -client = discord.Client(intents=intents) -tree = app_commands.CommandTree(client) - -# Invite link example -# https://discord.com/api/oauth2/authorize?client_id={DISCORD_CLIENT_ID}&permissions=2048&scope=bot - - -@register_deserializable -class DiscordBot(BaseBot): - def __init__(self, *args, **kwargs): - BaseBot.__init__(self, *args, **kwargs) - - def add_data(self, message): - data = message.split(" ")[-1] - try: - self.add(data) - response = f"Added data from: {data}" - except Exception: - logger.exception(f"Failed to add data {data}.") - response = "Some error occurred while adding data." - return response - - def ask_bot(self, message): - try: - response = self.query(message) - except Exception: - logger.exception(f"Failed to query {message}.") - response = "An error occurred. Please try again!" - return response - - def start(self): - client.run(os.environ["DISCORD_BOT_TOKEN"]) - - -# @tree decorator cannot be used in a class. A global discord_bot is used as a workaround. - - -@tree.command(name="question", description="ask embedchain") -async def query_command(interaction: discord.Interaction, question: str): - await interaction.response.defer() - member = client.guilds[0].get_member(client.user.id) - logger.info(f"User: {member}, Query: {question}") - try: - answer = discord_bot.ask_bot(question) - if args.include_question: - response = f"> {question}\n\n{answer}" - else: - response = answer - await interaction.followup.send(response) - except Exception as e: - await interaction.followup.send("An error occurred. Please try again!") - logger.error("Error occurred during 'query' command:", e) - - -@tree.command(name="add", description="add new content to the embedchain database") -async def add_command(interaction: discord.Interaction, url_or_text: str): - await interaction.response.defer() - member = client.guilds[0].get_member(client.user.id) - logger.info(f"User: {member}, Add: {url_or_text}") - try: - response = discord_bot.add_data(url_or_text) - await interaction.followup.send(response) - except Exception as e: - await interaction.followup.send("An error occurred. Please try again!") - logger.error("Error occurred during 'add' command:", e) - - -@tree.command(name="ping", description="Simple ping pong command") -async def ping(interaction: discord.Interaction): - await interaction.response.send_message("Pong", ephemeral=True) - - -@tree.error -async def on_app_command_error(interaction: discord.Interaction, error: discord.app_commands.AppCommandError) -> None: - if isinstance(error, commands.CommandNotFound): - await interaction.followup.send("Invalid command. Please refer to the documentation for correct syntax.") - else: - logger.error("Error occurred during command execution:", error) - - -@client.event -async def on_ready(): - # TODO: Sync in admin command, to not hit rate limits. - # This might be overkill for most users, and it would require to set a guild or user id, where sync is allowed. - await tree.sync() - logger.debug("Command tree synced") - logger.info(f"Logged in as {client.user.name}") - - -def start_command(): - parser = argparse.ArgumentParser(description="EmbedChain DiscordBot command line interface") - parser.add_argument( - "--include-question", - help="include question in query reply, otherwise it is hidden behind the slash command.", - action="store_true", - ) - global args - args = parser.parse_args() - - global discord_bot - discord_bot = DiscordBot() - discord_bot.start() - - -if __name__ == "__main__": - start_command() diff --git a/embedchain/embedchain/bots/poe.py b/embedchain/embedchain/bots/poe.py deleted file mode 100644 index 25c1bba5e..000000000 --- a/embedchain/embedchain/bots/poe.py +++ /dev/null @@ -1,87 +0,0 @@ -import argparse -import logging -import os -from typing import Optional - -from embedchain.helpers.json_serializable import register_deserializable - -from .base import BaseBot - -try: - from fastapi_poe import PoeBot, run -except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for Poe are not installed." "Please install with `pip install fastapi-poe==0.0.16`" - ) from None - - -def start_command(): - parser = argparse.ArgumentParser(description="EmbedChain PoeBot command line interface") - # parser.add_argument("--host", default="0.0.0.0", help="Host IP to bind") - parser.add_argument("--port", default=8080, type=int, help="Port to bind") - parser.add_argument("--api-key", type=str, help="Poe API key") - # parser.add_argument( - # "--history-length", - # default=5, - # type=int, - # help="Set the max size of the chat history. Multiplies cost, but improves conversation awareness.", - # ) - args = parser.parse_args() - - # FIXME: Arguments are automatically loaded by Poebot's ArgumentParser which causes it to fail. - # the port argument here is also just for show, it actually works because poe has the same argument. - - run(PoeBot(), api_key=args.api_key or os.environ.get("POE_API_KEY")) - - -@register_deserializable -class PoeBot(BaseBot, PoeBot): - def __init__(self): - self.history_length = 5 - super().__init__() - - async def get_response(self, query): - last_message = query.query[-1].content - try: - history = ( - [f"{m.role}: {m.content}" for m in query.query[-(self.history_length + 1) : -1]] - if len(query.query) > 0 - else None - ) - except Exception as e: - logging.error(f"Error when processing the chat history. Message is being sent without history. Error: {e}") - answer = self.handle_message(last_message, history) - yield self.text_event(answer) - - def handle_message(self, message, history: Optional[list[str]] = None): - if message.startswith("/add "): - response = self.add_data(message) - else: - response = self.ask_bot(message, history) - return response - - # def add_data(self, message): - # data = message.split(" ")[-1] - # try: - # self.add(data) - # response = f"Added data from: {data}" - # except Exception: - # logging.exception(f"Failed to add data {data}.") - # response = "Some error occurred while adding data." - # return response - - def ask_bot(self, message, history: list[str]): - try: - self.app.llm.set_history(history=history) - response = self.query(message) - except Exception: - logging.exception(f"Failed to query {message}.") - response = "An error occurred. Please try again!" - return response - - def start(self): - start_command() - - -if __name__ == "__main__": - start_command() diff --git a/embedchain/embedchain/bots/slack.py b/embedchain/embedchain/bots/slack.py deleted file mode 100644 index be23fddd9..000000000 --- a/embedchain/embedchain/bots/slack.py +++ /dev/null @@ -1,101 +0,0 @@ -import argparse -import logging -import os -import signal -import sys - -from embedchain import App -from embedchain.helpers.json_serializable import register_deserializable - -from .base import BaseBot - -try: - from flask import Flask, request - from slack_sdk import WebClient -except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for Slack are not installed." - "Please install with `pip install slack-sdk==3.21.3 flask==2.3.3`" - ) from None - - -logger = logging.getLogger(__name__) - -SLACK_BOT_TOKEN = os.environ.get("SLACK_BOT_TOKEN") - - -@register_deserializable -class SlackBot(BaseBot): - def __init__(self): - self.client = WebClient(token=SLACK_BOT_TOKEN) - self.chat_bot = App() - self.recent_message = {"ts": 0, "channel": ""} - super().__init__() - - def handle_message(self, event_data): - message = event_data.get("event") - if message and "text" in message and message.get("subtype") != "bot_message": - text: str = message["text"] - if float(message.get("ts")) > float(self.recent_message["ts"]): - self.recent_message["ts"] = message["ts"] - self.recent_message["channel"] = message["channel"] - if text.startswith("query"): - _, question = text.split(" ", 1) - try: - response = self.chat_bot.chat(question) - self.send_slack_message(message["channel"], response) - logger.info("Query answered successfully!") - except Exception as e: - self.send_slack_message(message["channel"], "An error occurred. Please try again!") - logger.error("Error occurred during 'query' command:", e) - elif text.startswith("add"): - _, data_type, url_or_text = text.split(" ", 2) - if url_or_text.startswith("<") and url_or_text.endswith(">"): - url_or_text = url_or_text[1:-1] - try: - self.chat_bot.add(url_or_text, data_type) - self.send_slack_message(message["channel"], f"Added {data_type} : {url_or_text}") - except ValueError as e: - self.send_slack_message(message["channel"], f"Error: {str(e)}") - logger.error("Error occurred during 'add' command:", e) - except Exception as e: - self.send_slack_message(message["channel"], f"Failed to add {data_type} : {url_or_text}") - logger.error("Error occurred during 'add' command:", e) - - def send_slack_message(self, channel, message): - response = self.client.chat_postMessage(channel=channel, text=message) - return response - - def start(self, host="0.0.0.0", port=5000, debug=True): - app = Flask(__name__) - - def signal_handler(sig, frame): - logger.info("\nGracefully shutting down the SlackBot...") - sys.exit(0) - - signal.signal(signal.SIGINT, signal_handler) - - @app.route("/", methods=["POST"]) - def chat(): - # Check if the request is a verification request - if request.json.get("challenge"): - return str(request.json.get("challenge")) - - response = self.handle_message(request.json) - return str(response) - - app.run(host=host, port=port, debug=debug) - - -def start_command(): - parser = argparse.ArgumentParser(description="EmbedChain SlackBot command line interface") - parser.add_argument("--host", default="0.0.0.0", help="Host IP to bind") - parser.add_argument("--port", default=5000, type=int, help="Port to bind") - args = parser.parse_args() - - slack_bot = SlackBot() - slack_bot.start(host=args.host, port=args.port) - - -if __name__ == "__main__": - start_command() diff --git a/embedchain/embedchain/bots/whatsapp.py b/embedchain/embedchain/bots/whatsapp.py deleted file mode 100644 index bec926bbe..000000000 --- a/embedchain/embedchain/bots/whatsapp.py +++ /dev/null @@ -1,83 +0,0 @@ -import argparse -import importlib -import logging -import signal -import sys - -from embedchain.helpers.json_serializable import register_deserializable - -from .base import BaseBot - -logger = logging.getLogger(__name__) - - -@register_deserializable -class WhatsAppBot(BaseBot): - def __init__(self): - try: - self.flask = importlib.import_module("flask") - self.twilio = importlib.import_module("twilio") - except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for WhatsApp are not installed. " - "Please install with `pip install twilio==8.5.0 flask==2.3.3`" - ) from None - super().__init__() - - def handle_message(self, message): - if message.startswith("add "): - response = self.add_data(message) - else: - response = self.ask_bot(message) - return response - - def add_data(self, message): - data = message.split(" ")[-1] - try: - self.add(data) - response = f"Added data from: {data}" - except Exception: - logger.exception(f"Failed to add data {data}.") - response = "Some error occurred while adding data." - return response - - def ask_bot(self, message): - try: - response = self.query(message) - except Exception: - logger.exception(f"Failed to query {message}.") - response = "An error occurred. Please try again!" - return response - - def start(self, host="0.0.0.0", port=5000, debug=True): - app = self.flask.Flask(__name__) - - def signal_handler(sig, frame): - logger.info("\nGracefully shutting down the WhatsAppBot...") - sys.exit(0) - - signal.signal(signal.SIGINT, signal_handler) - - @app.route("/chat", methods=["POST"]) - def chat(): - incoming_message = self.flask.request.values.get("Body", "").lower() - response = self.handle_message(incoming_message) - twilio_response = self.twilio.twiml.messaging_response.MessagingResponse() - twilio_response.message(response) - return str(twilio_response) - - app.run(host=host, port=port, debug=debug) - - -def start_command(): - parser = argparse.ArgumentParser(description="EmbedChain WhatsAppBot command line interface") - parser.add_argument("--host", default="0.0.0.0", help="Host IP to bind") - parser.add_argument("--port", default=5000, type=int, help="Port to bind") - args = parser.parse_args() - - whatsapp_bot = WhatsAppBot() - whatsapp_bot.start(host=args.host, port=args.port) - - -if __name__ == "__main__": - start_command() diff --git a/embedchain/embedchain/cache.py b/embedchain/embedchain/cache.py deleted file mode 100644 index 765141c3c..000000000 --- a/embedchain/embedchain/cache.py +++ /dev/null @@ -1,46 +0,0 @@ -import logging -import os # noqa: F401 -from typing import Any - -from gptcache import cache # noqa: F401 -from gptcache.adapter.adapter import adapt # noqa: F401 -from gptcache.config import Config # noqa: F401 -from gptcache.manager import get_data_manager -from gptcache.manager.scalar_data.base import Answer -from gptcache.manager.scalar_data.base import DataType as CacheDataType -from gptcache.session import Session -from gptcache.similarity_evaluation.distance import ( # noqa: F401 - SearchDistanceEvaluation, -) -from gptcache.similarity_evaluation.exact_match import ( # noqa: F401 - ExactMatchEvaluation, -) - -logger = logging.getLogger(__name__) - - -def gptcache_pre_function(data: dict[str, Any], **params: dict[str, Any]): - return data["input_query"] - - -def gptcache_data_manager(vector_dimension): - return get_data_manager(cache_base="sqlite", vector_base="chromadb", max_size=1000, eviction="LRU") - - -def gptcache_data_convert(cache_data): - logger.info("[Cache] Cache hit, returning cache data...") - return cache_data - - -def gptcache_update_cache_callback(llm_data, update_cache_func, *args, **kwargs): - logger.info("[Cache] Cache missed, updating cache...") - update_cache_func(Answer(llm_data, CacheDataType.STR)) - return llm_data - - -def _gptcache_session_hit_func(cur_session_id: str, cache_session_ids: list, cache_questions: list, cache_answer: str): - return cur_session_id in cache_session_ids - - -def get_gptcache_session(session_id: str): - return Session(name=session_id, check_hit_func=_gptcache_session_hit_func) diff --git a/embedchain/embedchain/chunkers/__init__.py b/embedchain/embedchain/chunkers/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/chunkers/audio.py b/embedchain/embedchain/chunkers/audio.py deleted file mode 100644 index 0aebda32e..000000000 --- a/embedchain/embedchain/chunkers/audio.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class AudioChunker(BaseChunker): - """Chunker for audio.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/base_chunker.py b/embedchain/embedchain/chunkers/base_chunker.py deleted file mode 100644 index 1f04a7d3f..000000000 --- a/embedchain/embedchain/chunkers/base_chunker.py +++ /dev/null @@ -1,94 +0,0 @@ -import hashlib -import logging -from typing import Any, Optional - -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import JSONSerializable -from embedchain.models.data_type import DataType - -logger = logging.getLogger(__name__) - - -class BaseChunker(JSONSerializable): - def __init__(self, text_splitter): - """Initialize the chunker.""" - self.text_splitter = text_splitter - self.data_type = None - - def create_chunks( - self, - loader, - src, - app_id=None, - config: Optional[ChunkerConfig] = None, - **kwargs: Optional[dict[str, Any]], - ): - """ - Loads data and chunks it. - - :param loader: The loader whose `load_data` method is used to create - the raw data. - :param src: The data to be handled by the loader. Can be a URL for - remote sources or local content for local loaders. - :param app_id: App id used to generate the doc_id. - """ - documents = [] - chunk_ids = [] - id_map = {} - min_chunk_size = config.min_chunk_size if config is not None else 1 - logger.info(f"Skipping chunks smaller than {min_chunk_size} characters") - data_result = loader.load_data(src, **kwargs) - data_records = data_result["data"] - doc_id = data_result["doc_id"] - # Prefix app_id in the document id if app_id is not None to - # distinguish between different documents stored in the same - # elasticsearch or opensearch index - doc_id = f"{app_id}--{doc_id}" if app_id is not None else doc_id - metadatas = [] - for data in data_records: - content = data["content"] - - metadata = data["meta_data"] - # add data type to meta data to allow query using data type - metadata["data_type"] = self.data_type.value - metadata["doc_id"] = doc_id - - # TODO: Currently defaulting to the src as the url. This is done intentianally since some - # of the data types like 'gmail' loader doesn't have the url in the meta data. - url = metadata.get("url", src) - - chunks = self.get_chunks(content) - for chunk in chunks: - chunk_id = hashlib.sha256((chunk + url).encode()).hexdigest() - chunk_id = f"{app_id}--{chunk_id}" if app_id is not None else chunk_id - if id_map.get(chunk_id) is None and len(chunk) >= min_chunk_size: - id_map[chunk_id] = True - chunk_ids.append(chunk_id) - documents.append(chunk) - metadatas.append(metadata) - return { - "documents": documents, - "ids": chunk_ids, - "metadatas": metadatas, - "doc_id": doc_id, - } - - def get_chunks(self, content): - """ - Returns chunks using text splitter instance. - - Override in child class if custom logic. - """ - return self.text_splitter.split_text(content) - - def set_data_type(self, data_type: DataType): - """ - set the data type of chunker - """ - self.data_type = data_type - - # TODO: This should be done during initialization. This means it has to be done in the child classes. - - @staticmethod - def get_word_count(documents) -> int: - return sum(len(document.split(" ")) for document in documents) diff --git a/embedchain/embedchain/chunkers/beehiiv.py b/embedchain/embedchain/chunkers/beehiiv.py deleted file mode 100644 index 7c130d542..000000000 --- a/embedchain/embedchain/chunkers/beehiiv.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class BeehiivChunker(BaseChunker): - """Chunker for Beehiiv.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/common_chunker.py b/embedchain/embedchain/chunkers/common_chunker.py deleted file mode 100644 index 53676d400..000000000 --- a/embedchain/embedchain/chunkers/common_chunker.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class CommonChunker(BaseChunker): - """Common chunker for all loaders.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=2000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/discourse.py b/embedchain/embedchain/chunkers/discourse.py deleted file mode 100644 index 14898bf01..000000000 --- a/embedchain/embedchain/chunkers/discourse.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class DiscourseChunker(BaseChunker): - """Chunker for discourse.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/docs_site.py b/embedchain/embedchain/chunkers/docs_site.py deleted file mode 100644 index d51dc8ee2..000000000 --- a/embedchain/embedchain/chunkers/docs_site.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class DocsSiteChunker(BaseChunker): - """Chunker for code docs site.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=500, chunk_overlap=50, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/docx_file.py b/embedchain/embedchain/chunkers/docx_file.py deleted file mode 100644 index 1452349e8..000000000 --- a/embedchain/embedchain/chunkers/docx_file.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class DocxFileChunker(BaseChunker): - """Chunker for .docx file.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/excel_file.py b/embedchain/embedchain/chunkers/excel_file.py deleted file mode 100644 index 7de00a52f..000000000 --- a/embedchain/embedchain/chunkers/excel_file.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class ExcelFileChunker(BaseChunker): - """Chunker for Excel file.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/gmail.py b/embedchain/embedchain/chunkers/gmail.py deleted file mode 100644 index 6b804f546..000000000 --- a/embedchain/embedchain/chunkers/gmail.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class GmailChunker(BaseChunker): - """Chunker for gmail.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/google_drive.py b/embedchain/embedchain/chunkers/google_drive.py deleted file mode 100644 index 8440325b5..000000000 --- a/embedchain/embedchain/chunkers/google_drive.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class GoogleDriveChunker(BaseChunker): - """Chunker for google drive folder.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/image.py b/embedchain/embedchain/chunkers/image.py deleted file mode 100644 index d29a84f4d..000000000 --- a/embedchain/embedchain/chunkers/image.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class ImageChunker(BaseChunker): - """Chunker for Images.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=2000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/json.py b/embedchain/embedchain/chunkers/json.py deleted file mode 100644 index ebc525419..000000000 --- a/embedchain/embedchain/chunkers/json.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class JSONChunker(BaseChunker): - """Chunker for json.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/mdx.py b/embedchain/embedchain/chunkers/mdx.py deleted file mode 100644 index 1c277dda7..000000000 --- a/embedchain/embedchain/chunkers/mdx.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class MdxChunker(BaseChunker): - """Chunker for mdx files.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/mysql.py b/embedchain/embedchain/chunkers/mysql.py deleted file mode 100644 index 2b1c11ace..000000000 --- a/embedchain/embedchain/chunkers/mysql.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class MySQLChunker(BaseChunker): - """Chunker for json.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/notion.py b/embedchain/embedchain/chunkers/notion.py deleted file mode 100644 index 190d59b57..000000000 --- a/embedchain/embedchain/chunkers/notion.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class NotionChunker(BaseChunker): - """Chunker for notion.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=300, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/openapi.py b/embedchain/embedchain/chunkers/openapi.py deleted file mode 100644 index fbe7b708b..000000000 --- a/embedchain/embedchain/chunkers/openapi.py +++ /dev/null @@ -1,18 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig - - -class OpenAPIChunker(BaseChunker): - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/pdf_file.py b/embedchain/embedchain/chunkers/pdf_file.py deleted file mode 100644 index 56bae064e..000000000 --- a/embedchain/embedchain/chunkers/pdf_file.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class PdfFileChunker(BaseChunker): - """Chunker for PDF file.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/postgres.py b/embedchain/embedchain/chunkers/postgres.py deleted file mode 100644 index 7c6859bd0..000000000 --- a/embedchain/embedchain/chunkers/postgres.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class PostgresChunker(BaseChunker): - """Chunker for postgres.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/qna_pair.py b/embedchain/embedchain/chunkers/qna_pair.py deleted file mode 100644 index c0d8277b1..000000000 --- a/embedchain/embedchain/chunkers/qna_pair.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class QnaPairChunker(BaseChunker): - """Chunker for QnA pair.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=300, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/rss_feed.py b/embedchain/embedchain/chunkers/rss_feed.py deleted file mode 100644 index 1767f9edd..000000000 --- a/embedchain/embedchain/chunkers/rss_feed.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class RSSFeedChunker(BaseChunker): - """Chunker for RSS Feed.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=2000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/sitemap.py b/embedchain/embedchain/chunkers/sitemap.py deleted file mode 100644 index 64e773742..000000000 --- a/embedchain/embedchain/chunkers/sitemap.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class SitemapChunker(BaseChunker): - """Chunker for sitemap.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=500, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/slack.py b/embedchain/embedchain/chunkers/slack.py deleted file mode 100644 index 595682beb..000000000 --- a/embedchain/embedchain/chunkers/slack.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class SlackChunker(BaseChunker): - """Chunker for postgres.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/substack.py b/embedchain/embedchain/chunkers/substack.py deleted file mode 100644 index 92cacd6cb..000000000 --- a/embedchain/embedchain/chunkers/substack.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class SubstackChunker(BaseChunker): - """Chunker for Substack.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/table.py b/embedchain/embedchain/chunkers/table.py deleted file mode 100644 index 567ed6541..000000000 --- a/embedchain/embedchain/chunkers/table.py +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig - - -class TableChunker(BaseChunker): - """Chunker for tables, for instance csv, google sheets or databases.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=300, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/text.py b/embedchain/embedchain/chunkers/text.py deleted file mode 100644 index f33d60c46..000000000 --- a/embedchain/embedchain/chunkers/text.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class TextChunker(BaseChunker): - """Chunker for text.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=300, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/unstructured_file.py b/embedchain/embedchain/chunkers/unstructured_file.py deleted file mode 100644 index d55f23ef0..000000000 --- a/embedchain/embedchain/chunkers/unstructured_file.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class UnstructuredFileChunker(BaseChunker): - """Chunker for Unstructured file.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/web_page.py b/embedchain/embedchain/chunkers/web_page.py deleted file mode 100644 index 5ef7f40df..000000000 --- a/embedchain/embedchain/chunkers/web_page.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class WebPageChunker(BaseChunker): - """Chunker for web page.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=2000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/xml.py b/embedchain/embedchain/chunkers/xml.py deleted file mode 100644 index c1bab0a77..000000000 --- a/embedchain/embedchain/chunkers/xml.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class XmlChunker(BaseChunker): - """Chunker for XML files.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=500, chunk_overlap=50, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/chunkers/youtube_video.py b/embedchain/embedchain/chunkers/youtube_video.py deleted file mode 100644 index bde0a8f78..000000000 --- a/embedchain/embedchain/chunkers/youtube_video.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -from langchain.text_splitter import RecursiveCharacterTextSplitter - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class YoutubeVideoChunker(BaseChunker): - """Chunker for Youtube video.""" - - def __init__(self, config: Optional[ChunkerConfig] = None): - if config is None: - config = ChunkerConfig(chunk_size=2000, chunk_overlap=0, length_function=len) - text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap, - length_function=config.length_function, - ) - super().__init__(text_splitter) diff --git a/embedchain/embedchain/cli.py b/embedchain/embedchain/cli.py deleted file mode 100644 index e4f0401d5..000000000 --- a/embedchain/embedchain/cli.py +++ /dev/null @@ -1,335 +0,0 @@ -import json -import os -import shutil -import signal -import subprocess -import sys -import tempfile -import time -import zipfile -from pathlib import Path - -import click -import requests -from rich.console import Console - -from embedchain.telemetry.posthog import AnonymousTelemetry -from embedchain.utils.cli import ( - deploy_fly, - deploy_gradio_app, - deploy_hf_spaces, - deploy_modal, - deploy_render, - deploy_streamlit, - get_pkg_path_from_name, - setup_fly_io_app, - setup_gradio_app, - setup_hf_app, - setup_modal_com_app, - setup_render_com_app, - setup_streamlit_io_app, -) - -console = Console() -api_process = None -ui_process = None - -anonymous_telemetry = AnonymousTelemetry() - - -def signal_handler(sig, frame): - """Signal handler to catch termination signals and kill server processes.""" - global api_process, ui_process - console.print("\n🛑 [bold yellow]Stopping servers...[/bold yellow]") - if api_process: - api_process.terminate() - console.print("🛑 [bold yellow]API server stopped.[/bold yellow]") - if ui_process: - ui_process.terminate() - console.print("🛑 [bold yellow]UI server stopped.[/bold yellow]") - sys.exit(0) - - -@click.group() -def cli(): - pass - - -@cli.command() -@click.argument("app_name") -@click.option("--docker", is_flag=True, help="Use docker to create the app.") -@click.pass_context -def create_app(ctx, app_name, docker): - if Path(app_name).exists(): - console.print( - f"❌ [red]Directory '{app_name}' already exists. Try using a new directory name, or remove it.[/red]" - ) - return - - os.makedirs(app_name) - os.chdir(app_name) - - # Step 1: Download the zip file - zip_url = "http://github.com/embedchain/ec-admin/archive/main.zip" - console.print(f"Creating a new embedchain app in [green]{Path().resolve()}[/green]\n") - try: - response = requests.get(zip_url) - response.raise_for_status() - with tempfile.NamedTemporaryFile(delete=False) as tmp_file: - tmp_file.write(response.content) - zip_file_path = tmp_file.name - console.print("✅ [bold green]Fetched template successfully.[/bold green]") - except requests.RequestException as e: - console.print(f"❌ [bold red]Failed to download zip file: {e}[/bold red]") - anonymous_telemetry.capture(event_name="ec_create_app", properties={"success": False}) - return - - # Step 2: Extract the zip file - try: - with zipfile.ZipFile(zip_file_path, "r") as zip_ref: - # Get the name of the root directory inside the zip file - root_dir = Path(zip_ref.namelist()[0]) - for member in zip_ref.infolist(): - # Build the path to extract the file to, skipping the root directory - target_file = Path(member.filename).relative_to(root_dir) - source_file = zip_ref.open(member, "r") - if member.is_dir(): - # Create directory if it doesn't exist - os.makedirs(target_file, exist_ok=True) - else: - with open(target_file, "wb") as file: - # Write the file - shutil.copyfileobj(source_file, file) - console.print("✅ [bold green]Extracted zip file successfully.[/bold green]") - anonymous_telemetry.capture(event_name="ec_create_app", properties={"success": True}) - except zipfile.BadZipFile: - console.print("❌ [bold red]Error in extracting zip file. The file might be corrupted.[/bold red]") - anonymous_telemetry.capture(event_name="ec_create_app", properties={"success": False}) - return - - if docker: - subprocess.run(["docker-compose", "build"], check=True) - else: - ctx.invoke(install_reqs) - - -@cli.command() -def install_reqs(): - try: - console.print("Installing python requirements...\n") - time.sleep(2) - os.chdir("api") - subprocess.run(["pip", "install", "-r", "requirements.txt"], check=True) - os.chdir("..") - console.print("\n ✅ [bold green]Installed API requirements successfully.[/bold green]\n") - except Exception as e: - console.print(f"❌ [bold red]Failed to install API requirements: {e}[/bold red]") - anonymous_telemetry.capture(event_name="ec_install_reqs", properties={"success": False}) - return - - try: - os.chdir("ui") - subprocess.run(["yarn"], check=True) - console.print("\n✅ [bold green]Successfully installed frontend requirements.[/bold green]") - anonymous_telemetry.capture(event_name="ec_install_reqs", properties={"success": True}) - except Exception as e: - console.print(f"❌ [bold red]Failed to install frontend requirements. Error: {e}[/bold red]") - anonymous_telemetry.capture(event_name="ec_install_reqs", properties={"success": False}) - - -@cli.command() -@click.option("--docker", is_flag=True, help="Run inside docker.") -def start(docker): - if docker: - subprocess.run(["docker-compose", "up"], check=True) - return - - # Set up signal handling - signal.signal(signal.SIGINT, signal_handler) - signal.signal(signal.SIGTERM, signal_handler) - - # Step 1: Start the API server - try: - os.chdir("api") - api_process = subprocess.Popen(["python", "-m", "main"], stdout=None, stderr=None) - os.chdir("..") - console.print("✅ [bold green]API server started successfully.[/bold green]") - except Exception as e: - console.print(f"❌ [bold red]Failed to start the API server: {e}[/bold red]") - anonymous_telemetry.capture(event_name="ec_start", properties={"success": False}) - return - - # Sleep for 2 seconds to give the user time to read the message - time.sleep(2) - - # Step 2: Install UI requirements and start the UI server - try: - os.chdir("ui") - subprocess.run(["yarn"], check=True) - ui_process = subprocess.Popen(["yarn", "dev"]) - console.print("✅ [bold green]UI server started successfully.[/bold green]") - anonymous_telemetry.capture(event_name="ec_start", properties={"success": True}) - except Exception as e: - console.print(f"❌ [bold red]Failed to start the UI server: {e}[/bold red]") - anonymous_telemetry.capture(event_name="ec_start", properties={"success": False}) - - # Keep the script running until it receives a kill signal - try: - api_process.wait() - ui_process.wait() - except KeyboardInterrupt: - console.print("\n🛑 [bold yellow]Stopping server...[/bold yellow]") - - -@cli.command() -@click.option("--template", default="fly.io", help="The template to use.") -@click.argument("extra_args", nargs=-1, type=click.UNPROCESSED) -def create(template, extra_args): - anonymous_telemetry.capture(event_name="ec_create", properties={"template_used": template}) - template_dir = template - if "/" in template_dir: - template_dir = template.split("/")[1] - src_path = get_pkg_path_from_name(template_dir) - shutil.copytree(src_path, os.getcwd(), dirs_exist_ok=True) - console.print(f"✅ [bold green]Successfully created app from template '{template}'.[/bold green]") - - if template == "fly.io": - setup_fly_io_app(extra_args) - elif template == "modal.com": - setup_modal_com_app(extra_args) - elif template == "render.com": - setup_render_com_app() - elif template == "streamlit.io": - setup_streamlit_io_app() - elif template == "gradio.app": - setup_gradio_app() - elif template == "hf/gradio.app" or template == "hf/streamlit.io": - setup_hf_app() - else: - raise ValueError(f"Unknown template '{template}'.") - - embedchain_config = {"provider": template} - with open("embedchain.json", "w") as file: - json.dump(embedchain_config, file, indent=4) - console.print( - f"🎉 [green]All done! Successfully created `embedchain.json` with '{template}' as provider.[/green]" - ) - - -def run_dev_fly_io(debug, host, port): - uvicorn_command = ["uvicorn", "app:app"] - - if debug: - uvicorn_command.append("--reload") - - uvicorn_command.extend(["--host", host, "--port", str(port)]) - - try: - console.print(f"🚀 [bold cyan]Running FastAPI app with command: {' '.join(uvicorn_command)}[/bold cyan]") - subprocess.run(uvicorn_command, check=True) - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except KeyboardInterrupt: - console.print("\n🛑 [bold yellow]FastAPI server stopped[/bold yellow]") - - -def run_dev_modal_com(): - modal_run_cmd = ["modal", "serve", "app"] - try: - console.print(f"🚀 [bold cyan]Running FastAPI app with command: {' '.join(modal_run_cmd)}[/bold cyan]") - subprocess.run(modal_run_cmd, check=True) - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except KeyboardInterrupt: - console.print("\n🛑 [bold yellow]FastAPI server stopped[/bold yellow]") - - -def run_dev_streamlit_io(): - streamlit_run_cmd = ["streamlit", "run", "app.py"] - try: - console.print(f"🚀 [bold cyan]Running Streamlit app with command: {' '.join(streamlit_run_cmd)}[/bold cyan]") - subprocess.run(streamlit_run_cmd, check=True) - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except KeyboardInterrupt: - console.print("\n🛑 [bold yellow]Streamlit server stopped[/bold yellow]") - - -def run_dev_render_com(debug, host, port): - uvicorn_command = ["uvicorn", "app:app"] - - if debug: - uvicorn_command.append("--reload") - - uvicorn_command.extend(["--host", host, "--port", str(port)]) - - try: - console.print(f"🚀 [bold cyan]Running FastAPI app with command: {' '.join(uvicorn_command)}[/bold cyan]") - subprocess.run(uvicorn_command, check=True) - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except KeyboardInterrupt: - console.print("\n🛑 [bold yellow]FastAPI server stopped[/bold yellow]") - - -def run_dev_gradio(): - gradio_run_cmd = ["gradio", "app.py"] - try: - console.print(f"🚀 [bold cyan]Running Gradio app with command: {' '.join(gradio_run_cmd)}[/bold cyan]") - subprocess.run(gradio_run_cmd, check=True) - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except KeyboardInterrupt: - console.print("\n🛑 [bold yellow]Gradio server stopped[/bold yellow]") - - -@cli.command() -@click.option("--debug", is_flag=True, help="Enable or disable debug mode.") -@click.option("--host", default="127.0.0.1", help="The host address to run the FastAPI app on.") -@click.option("--port", default=8000, help="The port to run the FastAPI app on.") -def dev(debug, host, port): - template = "" - with open("embedchain.json", "r") as file: - embedchain_config = json.load(file) - template = embedchain_config["provider"] - - anonymous_telemetry.capture(event_name="ec_dev", properties={"template_used": template}) - if template == "fly.io": - run_dev_fly_io(debug, host, port) - elif template == "modal.com": - run_dev_modal_com() - elif template == "render.com": - run_dev_render_com(debug, host, port) - elif template == "streamlit.io" or template == "hf/streamlit.io": - run_dev_streamlit_io() - elif template == "gradio.app" or template == "hf/gradio.app": - run_dev_gradio() - else: - raise ValueError(f"Unknown template '{template}'.") - - -@cli.command() -def deploy(): - # Check for platform-specific files - template = "" - ec_app_name = "" - with open("embedchain.json", "r") as file: - embedchain_config = json.load(file) - ec_app_name = embedchain_config["name"] if "name" in embedchain_config else None - template = embedchain_config["provider"] - - anonymous_telemetry.capture(event_name="ec_deploy", properties={"template_used": template}) - if template == "fly.io": - deploy_fly() - elif template == "modal.com": - deploy_modal() - elif template == "render.com": - deploy_render() - elif template == "streamlit.io": - deploy_streamlit() - elif template == "gradio.app": - deploy_gradio_app() - elif template.startswith("hf/"): - deploy_hf_spaces(ec_app_name) - else: - console.print("❌ [bold red]No recognized deployment platform found.[/bold red]") diff --git a/embedchain/embedchain/client.py b/embedchain/embedchain/client.py deleted file mode 100644 index 7e8fcddbb..000000000 --- a/embedchain/embedchain/client.py +++ /dev/null @@ -1,103 +0,0 @@ -import json -import logging -import os -import uuid - -import requests - -from embedchain.constants import CONFIG_DIR, CONFIG_FILE - -logger = logging.getLogger(__name__) - - -class Client: - def __init__(self, api_key=None, host="https://apiv2.embedchain.ai"): - self.config_data = self.load_config() - self.host = host - - if api_key: - if self.check(api_key): - self.api_key = api_key - self.save() - else: - raise ValueError( - "Invalid API key provided. You can find your API key on https://app.embedchain.ai/settings/keys." - ) - else: - if "api_key" in self.config_data: - self.api_key = self.config_data["api_key"] - logger.info("API key loaded successfully!") - else: - raise ValueError( - "You are not logged in. Please obtain an API key from https://app.embedchain.ai/settings/keys/" - ) - - @classmethod - def setup(cls): - """ - Loads the user id from the config file if it exists, otherwise generates a new - one and saves it to the config file. - - :return: user id - :rtype: str - """ - os.makedirs(CONFIG_DIR, exist_ok=True) - - if os.path.exists(CONFIG_FILE): - with open(CONFIG_FILE, "r") as f: - data = json.load(f) - if "user_id" in data: - return data["user_id"] - - u_id = str(uuid.uuid4()) - with open(CONFIG_FILE, "w") as f: - json.dump({"user_id": u_id}, f) - - @classmethod - def load_config(cls): - if not os.path.exists(CONFIG_FILE): - cls.setup() - - with open(CONFIG_FILE, "r") as config_file: - return json.load(config_file) - - def save(self): - self.config_data["api_key"] = self.api_key - with open(CONFIG_FILE, "w") as config_file: - json.dump(self.config_data, config_file, indent=4) - - logger.info("API key saved successfully!") - - def clear(self): - if "api_key" in self.config_data: - del self.config_data["api_key"] - with open(CONFIG_FILE, "w") as config_file: - json.dump(self.config_data, config_file, indent=4) - self.api_key = None - logger.info("API key deleted successfully!") - else: - logger.warning("API key not found in the configuration file.") - - def update(self, api_key): - if self.check(api_key): - self.api_key = api_key - self.save() - logger.info("API key updated successfully!") - else: - logger.warning("Invalid API key provided. API key not updated.") - - def check(self, api_key): - validation_url = f"{self.host}/api/v1/accounts/api_keys/validate/" - response = requests.post(validation_url, headers={"Authorization": f"Token {api_key}"}) - if response.status_code == 200: - return True - else: - logger.warning(f"Response from API: {response.text}") - logger.warning("Invalid API key. Unable to validate.") - return False - - def get(self): - return self.api_key - - def __str__(self): - return self.api_key diff --git a/embedchain/embedchain/config/__init__.py b/embedchain/embedchain/config/__init__.py deleted file mode 100644 index 768408b78..000000000 --- a/embedchain/embedchain/config/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# flake8: noqa: F401 - -from .add_config import AddConfig, ChunkerConfig -from .app_config import AppConfig -from .base_config import BaseConfig -from .cache_config import CacheConfig -from .embedder.base import BaseEmbedderConfig -from .embedder.base import BaseEmbedderConfig as EmbedderConfig -from .embedder.ollama import OllamaEmbedderConfig -from .llm.base import BaseLlmConfig -from .mem0_config import Mem0Config -from .vector_db.chroma import ChromaDbConfig -from .vector_db.elasticsearch import ElasticsearchDBConfig -from .vector_db.opensearch import OpenSearchDBConfig -from .vector_db.zilliz import ZillizDBConfig diff --git a/embedchain/embedchain/config/add_config.py b/embedchain/embedchain/config/add_config.py deleted file mode 100644 index 56686e8ec..000000000 --- a/embedchain/embedchain/config/add_config.py +++ /dev/null @@ -1,79 +0,0 @@ -import builtins -import logging -from collections.abc import Callable -from importlib import import_module -from typing import Optional - -from embedchain.config.base_config import BaseConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class ChunkerConfig(BaseConfig): - """ - Config for the chunker used in `add` method - """ - - def __init__( - self, - chunk_size: Optional[int] = 2000, - chunk_overlap: Optional[int] = 0, - length_function: Optional[Callable[[str], int]] = None, - min_chunk_size: Optional[int] = 0, - ): - self.chunk_size = chunk_size - self.chunk_overlap = chunk_overlap - self.min_chunk_size = min_chunk_size - if self.min_chunk_size >= self.chunk_size: - raise ValueError(f"min_chunk_size {min_chunk_size} should be less than chunk_size {chunk_size}") - if self.min_chunk_size < self.chunk_overlap: - logging.warning( - f"min_chunk_size {min_chunk_size} should be greater than chunk_overlap {chunk_overlap}, otherwise it is redundant." # noqa:E501 - ) - - if isinstance(length_function, str): - self.length_function = self.load_func(length_function) - else: - self.length_function = length_function if length_function else len - - @staticmethod - def load_func(dotpath: str): - if "." not in dotpath: - return getattr(builtins, dotpath) - else: - module_, func = dotpath.rsplit(".", maxsplit=1) - m = import_module(module_) - return getattr(m, func) - - -@register_deserializable -class LoaderConfig(BaseConfig): - """ - Config for the loader used in `add` method - """ - - def __init__(self): - pass - - -@register_deserializable -class AddConfig(BaseConfig): - """ - Config for the `add` method. - """ - - def __init__( - self, - chunker: Optional[ChunkerConfig] = None, - loader: Optional[LoaderConfig] = None, - ): - """ - Initializes a configuration class instance for the `add` method. - - :param chunker: Chunker config, defaults to None - :type chunker: Optional[ChunkerConfig], optional - :param loader: Loader config, defaults to None - :type loader: Optional[LoaderConfig], optional - """ - self.loader = loader - self.chunker = chunker diff --git a/embedchain/embedchain/config/app_config.py b/embedchain/embedchain/config/app_config.py deleted file mode 100644 index f3b571b7f..000000000 --- a/embedchain/embedchain/config/app_config.py +++ /dev/null @@ -1,34 +0,0 @@ -from typing import Optional - -from embedchain.helpers.json_serializable import register_deserializable - -from .base_app_config import BaseAppConfig - - -@register_deserializable -class AppConfig(BaseAppConfig): - """ - Config to initialize an embedchain custom `App` instance, with extra config options. - """ - - def __init__( - self, - log_level: str = "WARNING", - id: Optional[str] = None, - name: Optional[str] = None, - collect_metrics: Optional[bool] = True, - **kwargs, - ): - """ - Initializes a configuration class instance for an App. This is the simplest form of an embedchain app. - Most of the configuration is done in the `App` class itself. - - :param log_level: Debug level ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], defaults to "WARNING" - :type log_level: str, optional - :param id: ID of the app. Document metadata will have this id., defaults to None - :type id: Optional[str], optional - :param collect_metrics: Send anonymous telemetry to improve embedchain, defaults to True - :type collect_metrics: Optional[bool], optional - """ - self.name = name - super().__init__(log_level=log_level, id=id, collect_metrics=collect_metrics, **kwargs) diff --git a/embedchain/embedchain/config/base_app_config.py b/embedchain/embedchain/config/base_app_config.py deleted file mode 100644 index 781ca024a..000000000 --- a/embedchain/embedchain/config/base_app_config.py +++ /dev/null @@ -1,58 +0,0 @@ -import logging -from typing import Optional - -from embedchain.config.base_config import BaseConfig -from embedchain.helpers.json_serializable import JSONSerializable -from embedchain.vectordb.base import BaseVectorDB - -logger = logging.getLogger(__name__) - - -class BaseAppConfig(BaseConfig, JSONSerializable): - """ - Parent config to initialize an instance of `App`. - """ - - def __init__( - self, - log_level: str = "WARNING", - db: Optional[BaseVectorDB] = None, - id: Optional[str] = None, - collect_metrics: bool = True, - collection_name: Optional[str] = None, - ): - """ - Initializes a configuration class instance for an App. - Most of the configuration is done in the `App` class itself. - - :param log_level: Debug level ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], defaults to "WARNING" - :type log_level: str, optional - :param db: A database class. It is recommended to set this directly in the `App` class, not this config, - defaults to None - :type db: Optional[BaseVectorDB], optional - :param id: ID of the app. Document metadata will have this id., defaults to None - :type id: Optional[str], optional - :param collect_metrics: Send anonymous telemetry to improve embedchain, defaults to True - :type collect_metrics: Optional[bool], optional - :param collection_name: Default collection name. It's recommended to use app.db.set_collection_name() instead, - defaults to None - :type collection_name: Optional[str], optional - """ - self.id = id - self.collect_metrics = True if (collect_metrics is True or collect_metrics is None) else False - self.collection_name = collection_name - - if db: - self._db = db - logger.warning( - "DEPRECATION WARNING: Please supply the database as the second parameter during app init. " - "Such as `app(config=config, db=db)`." - ) - - if collection_name: - logger.warning("DEPRECATION WARNING: Please supply the collection name to the database config.") - return - - def _setup_logging(self, log_level): - logger.basicConfig(format="%(asctime)s [%(name)s] [%(levelname)s] %(message)s", level=log_level) - self.logger = logger.getLogger(__name__) diff --git a/embedchain/embedchain/config/base_config.py b/embedchain/embedchain/config/base_config.py deleted file mode 100644 index bf7869f41..000000000 --- a/embedchain/embedchain/config/base_config.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Any - -from embedchain.helpers.json_serializable import JSONSerializable - - -class BaseConfig(JSONSerializable): - """ - Base config. - """ - - def __init__(self): - """Initializes a configuration class for a class.""" - pass - - def as_dict(self) -> dict[str, Any]: - """Return config object as a dict - - :return: config object as dict - :rtype: dict[str, Any] - """ - return vars(self) diff --git a/embedchain/embedchain/config/cache_config.py b/embedchain/embedchain/config/cache_config.py deleted file mode 100644 index ef8bd1fb3..000000000 --- a/embedchain/embedchain/config/cache_config.py +++ /dev/null @@ -1,96 +0,0 @@ -from typing import Any, Optional - -from embedchain.config.base_config import BaseConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class CacheSimilarityEvalConfig(BaseConfig): - """ - This is the evaluator to compare two embeddings according to their distance computed in embedding retrieval stage. - In the retrieval stage, `search_result` is the distance used for approximate nearest neighbor search and have been - put into `cache_dict`. `max_distance` is used to bound this distance to make it between [0-`max_distance`]. - `positive` is used to indicate this distance is directly proportional to the similarity of two entities. - If `positive` is set `False`, `max_distance` will be used to subtract this distance to get the final score. - - :param max_distance: the bound of maximum distance. - :type max_distance: float - :param positive: if the larger distance indicates more similar of two entities, It is True. Otherwise, it is False. - :type positive: bool - """ - - def __init__( - self, - strategy: Optional[str] = "distance", - max_distance: Optional[float] = 1.0, - positive: Optional[bool] = False, - ): - self.strategy = strategy - self.max_distance = max_distance - self.positive = positive - - @staticmethod - def from_config(config: Optional[dict[str, Any]]): - if config is None: - return CacheSimilarityEvalConfig() - else: - return CacheSimilarityEvalConfig( - strategy=config.get("strategy", "distance"), - max_distance=config.get("max_distance", 1.0), - positive=config.get("positive", False), - ) - - -@register_deserializable -class CacheInitConfig(BaseConfig): - """ - This is a cache init config. Used to initialize a cache. - - :param similarity_threshold: a threshold ranged from 0 to 1 to filter search results with similarity score higher \ - than the threshold. When it is 0, there is no hits. When it is 1, all search results will be returned as hits. - :type similarity_threshold: float - :param auto_flush: it will be automatically flushed every time xx pieces of data are added, default to 20 - :type auto_flush: int - """ - - def __init__( - self, - similarity_threshold: Optional[float] = 0.8, - auto_flush: Optional[int] = 20, - ): - if similarity_threshold < 0 or similarity_threshold > 1: - raise ValueError(f"similarity_threshold {similarity_threshold} should be between 0 and 1") - - self.similarity_threshold = similarity_threshold - self.auto_flush = auto_flush - - @staticmethod - def from_config(config: Optional[dict[str, Any]]): - if config is None: - return CacheInitConfig() - else: - return CacheInitConfig( - similarity_threshold=config.get("similarity_threshold", 0.8), - auto_flush=config.get("auto_flush", 20), - ) - - -@register_deserializable -class CacheConfig(BaseConfig): - def __init__( - self, - similarity_eval_config: Optional[CacheSimilarityEvalConfig] = CacheSimilarityEvalConfig(), - init_config: Optional[CacheInitConfig] = CacheInitConfig(), - ): - self.similarity_eval_config = similarity_eval_config - self.init_config = init_config - - @staticmethod - def from_config(config: Optional[dict[str, Any]]): - if config is None: - return CacheConfig() - else: - return CacheConfig( - similarity_eval_config=CacheSimilarityEvalConfig.from_config(config.get("similarity_evaluation", {})), - init_config=CacheInitConfig.from_config(config.get("init_config", {})), - ) diff --git a/embedchain/embedchain/config/embedder/__init__.py b/embedchain/embedchain/config/embedder/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/config/embedder/aws_bedrock.py b/embedchain/embedchain/config/embedder/aws_bedrock.py deleted file mode 100644 index f0bd0c538..000000000 --- a/embedchain/embedchain/config/embedder/aws_bedrock.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Any, Dict, Optional - -from embedchain.config.embedder.base import BaseEmbedderConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class AWSBedrockEmbedderConfig(BaseEmbedderConfig): - def __init__( - self, - model: Optional[str] = None, - deployment_name: Optional[str] = None, - vector_dimension: Optional[int] = None, - task_type: Optional[str] = None, - title: Optional[str] = None, - model_kwargs: Optional[Dict[str, Any]] = None, - ): - super().__init__(model, deployment_name, vector_dimension) - self.task_type = task_type or "retrieval_document" - self.title = title or "Embeddings for Embedchain" - self.model_kwargs = model_kwargs or {} diff --git a/embedchain/embedchain/config/embedder/base.py b/embedchain/embedchain/config/embedder/base.py deleted file mode 100644 index 56c4070d0..000000000 --- a/embedchain/embedchain/config/embedder/base.py +++ /dev/null @@ -1,55 +0,0 @@ -from typing import Any, Dict, Optional, Union - -import httpx - -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class BaseEmbedderConfig: - def __init__( - self, - model: Optional[str] = None, - deployment_name: Optional[str] = None, - vector_dimension: Optional[int] = None, - endpoint: Optional[str] = None, - api_key: Optional[str] = None, - api_base: Optional[str] = None, - model_kwargs: Optional[Dict[str, Any]] = None, - http_client_proxies: Optional[Union[Dict, str]] = None, - http_async_client_proxies: Optional[Union[Dict, str]] = None, - ): - """ - Initialize a new instance of an embedder config class. - - :param model: model name of the llm embedding model (not applicable to all providers), defaults to None - :type model: Optional[str], optional - :param deployment_name: deployment name for llm embedding model, defaults to None - :type deployment_name: Optional[str], optional - :param vector_dimension: vector dimension of the embedding model, defaults to None - :type vector_dimension: Optional[int], optional - :param endpoint: endpoint for the embedding model, defaults to None - :type endpoint: Optional[str], optional - :param api_key: hugginface api key, defaults to None - :type api_key: Optional[str], optional - :param api_base: huggingface api base, defaults to None - :type api_base: Optional[str], optional - :param model_kwargs: key-value arguments for the embedding model, defaults a dict inside init. - :type model_kwargs: Optional[Dict[str, Any]], defaults a dict inside init. - :param http_client_proxies: The proxy server settings used to create self.http_client, defaults to None - :type http_client_proxies: Optional[Dict | str], optional - :param http_async_client_proxies: The proxy server settings for async calls used to create - self.http_async_client, defaults to None - :type http_async_client_proxies: Optional[Dict | str], optional - """ - self.model = model - self.deployment_name = deployment_name - self.vector_dimension = vector_dimension - self.endpoint = endpoint - self.api_key = api_key - self.api_base = api_base - self.model_kwargs = model_kwargs or {} - self.http_client = httpx.Client(proxies=http_client_proxies) if http_client_proxies else None - self.http_async_client = ( - httpx.AsyncClient(proxies=http_async_client_proxies) if http_async_client_proxies else None - ) diff --git a/embedchain/embedchain/config/embedder/google.py b/embedchain/embedchain/config/embedder/google.py deleted file mode 100644 index 7cf5a9011..000000000 --- a/embedchain/embedchain/config/embedder/google.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Optional - -from embedchain.config.embedder.base import BaseEmbedderConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class GoogleAIEmbedderConfig(BaseEmbedderConfig): - def __init__( - self, - model: Optional[str] = None, - deployment_name: Optional[str] = None, - vector_dimension: Optional[int] = None, - task_type: Optional[str] = None, - title: Optional[str] = None, - ): - super().__init__(model, deployment_name, vector_dimension) - self.task_type = task_type or "retrieval_document" - self.title = title or "Embeddings for Embedchain" diff --git a/embedchain/embedchain/config/embedder/ollama.py b/embedchain/embedchain/config/embedder/ollama.py deleted file mode 100644 index f680328f9..000000000 --- a/embedchain/embedchain/config/embedder/ollama.py +++ /dev/null @@ -1,16 +0,0 @@ -from typing import Optional - -from embedchain.config.embedder.base import BaseEmbedderConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class OllamaEmbedderConfig(BaseEmbedderConfig): - def __init__( - self, - model: Optional[str] = None, - base_url: Optional[str] = None, - vector_dimension: Optional[int] = None, - ): - super().__init__(model=model, vector_dimension=vector_dimension) - self.base_url = base_url or "http://localhost:11434" diff --git a/embedchain/embedchain/config/evaluation/__init__.py b/embedchain/embedchain/config/evaluation/__init__.py deleted file mode 100644 index 67e78dade..000000000 --- a/embedchain/embedchain/config/evaluation/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from .base import ( # noqa: F401 - AnswerRelevanceConfig, - ContextRelevanceConfig, - GroundednessConfig, -) diff --git a/embedchain/embedchain/config/evaluation/base.py b/embedchain/embedchain/config/evaluation/base.py deleted file mode 100644 index 5c44d3f83..000000000 --- a/embedchain/embedchain/config/evaluation/base.py +++ /dev/null @@ -1,92 +0,0 @@ -from typing import Optional - -from embedchain.config.base_config import BaseConfig - -ANSWER_RELEVANCY_PROMPT = """ -Please provide $num_gen_questions questions from the provided answer. -You must provide the complete question, if are not able to provide the complete question, return empty string (""). -Please only provide one question per line without numbers or bullets to distinguish them. -You must only provide the questions and no other text. - -$answer -""" # noqa:E501 - - -CONTEXT_RELEVANCY_PROMPT = """ -Please extract relevant sentences from the provided context that is required to answer the given question. -If no relevant sentences are found, or if you believe the question cannot be answered from the given context, return the empty string (""). -While extracting candidate sentences you're not allowed to make any changes to sentences from given context or make up any sentences. -You must only provide sentences from the given context and nothing else. - -Context: $context -Question: $question -""" # noqa:E501 - -GROUNDEDNESS_ANSWER_CLAIMS_PROMPT = """ -Please provide one or more statements from each sentence of the provided answer. -You must provide the symantically equivalent statements for each sentence of the answer. -You must provide the complete statement, if are not able to provide the complete statement, return empty string (""). -Please only provide one statement per line WITHOUT numbers or bullets. -If the question provided is not being answered in the provided answer, return empty string (""). -You must only provide the statements and no other text. - -$question -$answer -""" # noqa:E501 - -GROUNDEDNESS_CLAIMS_INFERENCE_PROMPT = """ -Given the context and the provided claim statements, please provide a verdict for each claim statement whether it can be completely inferred from the given context or not. -Use only "1" (yes), "0" (no) and "-1" (null) for "yes", "no" or "null" respectively. -You must provide one verdict per line, ONLY WITH "1", "0" or "-1" as per your verdict to the given statement and nothing else. -You must provide the verdicts in the same order as the claim statements. - -Contexts: -$context - -Claim statements: -$claim_statements -""" # noqa:E501 - - -class GroundednessConfig(BaseConfig): - def __init__( - self, - model: str = "gpt-4", - api_key: Optional[str] = None, - answer_claims_prompt: str = GROUNDEDNESS_ANSWER_CLAIMS_PROMPT, - claims_inference_prompt: str = GROUNDEDNESS_CLAIMS_INFERENCE_PROMPT, - ): - self.model = model - self.api_key = api_key - self.answer_claims_prompt = answer_claims_prompt - self.claims_inference_prompt = claims_inference_prompt - - -class AnswerRelevanceConfig(BaseConfig): - def __init__( - self, - model: str = "gpt-4", - embedder: str = "text-embedding-ada-002", - api_key: Optional[str] = None, - num_gen_questions: int = 1, - prompt: str = ANSWER_RELEVANCY_PROMPT, - ): - self.model = model - self.embedder = embedder - self.api_key = api_key - self.num_gen_questions = num_gen_questions - self.prompt = prompt - - -class ContextRelevanceConfig(BaseConfig): - def __init__( - self, - model: str = "gpt-4", - api_key: Optional[str] = None, - language: str = "en", - prompt: str = CONTEXT_RELEVANCY_PROMPT, - ): - self.model = model - self.api_key = api_key - self.language = language - self.prompt = prompt diff --git a/embedchain/embedchain/config/llm/__init__.py b/embedchain/embedchain/config/llm/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/config/llm/base.py b/embedchain/embedchain/config/llm/base.py deleted file mode 100644 index 693d09c5b..000000000 --- a/embedchain/embedchain/config/llm/base.py +++ /dev/null @@ -1,276 +0,0 @@ -import json -import logging -import re -from pathlib import Path -from string import Template -from typing import Any, Dict, Mapping, Optional, Union - -import httpx - -from embedchain.config.base_config import BaseConfig -from embedchain.helpers.json_serializable import register_deserializable - -logger = logging.getLogger(__name__) - -DEFAULT_PROMPT = """ -You are a Q&A expert system. Your responses must always be rooted in the context provided for each query. Here are some guidelines to follow: - -1. Refrain from explicitly mentioning the context provided in your response. -2. The context should silently guide your answers without being directly acknowledged. -3. Do not use phrases such as 'According to the context provided', 'Based on the context, ...' etc. - -Context information: ----------------------- -$context ----------------------- - -Query: $query -Answer: -""" # noqa:E501 - -DEFAULT_PROMPT_WITH_HISTORY = """ -You are a Q&A expert system. Your responses must always be rooted in the context provided for each query. You are also provided with the conversation history with the user. Make sure to use relevant context from conversation history as needed. - -Here are some guidelines to follow: - -1. Refrain from explicitly mentioning the context provided in your response. -2. The context should silently guide your answers without being directly acknowledged. -3. Do not use phrases such as 'According to the context provided', 'Based on the context, ...' etc. - -Context information: ----------------------- -$context ----------------------- - -Conversation history: ----------------------- -$history ----------------------- - -Query: $query -Answer: -""" # noqa:E501 - -DEFAULT_PROMPT_WITH_MEM0_MEMORY = """ -You are an expert at answering questions based on provided memories. You are also provided with the context and conversation history of the user. Make sure to use relevant context from conversation history and context as needed. - -Here are some guidelines to follow: -1. Refrain from explicitly mentioning the context provided in your response. -2. Take into consideration the conversation history and context provided. -3. Do not use phrases such as 'According to the context provided', 'Based on the context, ...' etc. - -Striclty return the query exactly as it is if it is not a question or if no relevant information is found. - -Context information: ----------------------- -$context ----------------------- - -Conversation history: ----------------------- -$history ----------------------- - -Memories/Preferences: ----------------------- -$memories ----------------------- - -Query: $query -Answer: -""" # noqa:E501 - -DOCS_SITE_DEFAULT_PROMPT = """ -You are an expert AI assistant for developer support product. Your responses must always be rooted in the context provided for each query. Wherever possible, give complete code snippet. Dont make up any code snippet on your own. - -Here are some guidelines to follow: - -1. Refrain from explicitly mentioning the context provided in your response. -2. The context should silently guide your answers without being directly acknowledged. -3. Do not use phrases such as 'According to the context provided', 'Based on the context, ...' etc. - -Context information: ----------------------- -$context ----------------------- - -Query: $query -Answer: -""" # noqa:E501 - -DEFAULT_PROMPT_TEMPLATE = Template(DEFAULT_PROMPT) -DEFAULT_PROMPT_WITH_HISTORY_TEMPLATE = Template(DEFAULT_PROMPT_WITH_HISTORY) -DEFAULT_PROMPT_WITH_MEM0_MEMORY_TEMPLATE = Template(DEFAULT_PROMPT_WITH_MEM0_MEMORY) -DOCS_SITE_PROMPT_TEMPLATE = Template(DOCS_SITE_DEFAULT_PROMPT) -query_re = re.compile(r"\$\{*query\}*") -context_re = re.compile(r"\$\{*context\}*") -history_re = re.compile(r"\$\{*history\}*") - - -@register_deserializable -class BaseLlmConfig(BaseConfig): - """ - Config for the `query` method. - """ - - def __init__( - self, - number_documents: int = 3, - template: Optional[Template] = None, - prompt: Optional[Template] = None, - model: Optional[str] = None, - temperature: float = 0, - max_tokens: int = 1000, - top_p: float = 1, - stream: bool = False, - online: bool = False, - token_usage: bool = False, - deployment_name: Optional[str] = None, - system_prompt: Optional[str] = None, - where: dict[str, Any] = None, - query_type: Optional[str] = None, - callbacks: Optional[list] = None, - api_key: Optional[str] = None, - base_url: Optional[str] = None, - endpoint: Optional[str] = None, - model_kwargs: Optional[dict[str, Any]] = None, - http_client_proxies: Optional[Union[Dict, str]] = None, - http_async_client_proxies: Optional[Union[Dict, str]] = None, - local: Optional[bool] = False, - default_headers: Optional[Mapping[str, str]] = None, - api_version: Optional[str] = None, - ): - """ - Initializes a configuration class instance for the LLM. - - Takes the place of the former `QueryConfig` or `ChatConfig`. - - :param number_documents: Number of documents to pull from the database as - context, defaults to 1 - :type number_documents: int, optional - :param template: The `Template` instance to use as a template for - prompt, defaults to None (deprecated) - :type template: Optional[Template], optional - :param prompt: The `Template` instance to use as a template for - prompt, defaults to None - :type prompt: Optional[Template], optional - :param model: Controls the OpenAI model used, defaults to None - :type model: Optional[str], optional - :param temperature: Controls the randomness of the model's output. - Higher values (closer to 1) make output more random, lower values make it more deterministic, defaults to 0 - :type temperature: float, optional - :param max_tokens: Controls how many tokens are generated, defaults to 1000 - :type max_tokens: int, optional - :param top_p: Controls the diversity of words. Higher values (closer to 1) make word selection more diverse, - defaults to 1 - :type top_p: float, optional - :param stream: Control if response is streamed back to user, defaults to False - :type stream: bool, optional - :param online: Controls whether to use internet for answering query, defaults to False - :type online: bool, optional - :param token_usage: Controls whether to return token usage in response, defaults to False - :type token_usage: bool, optional - :param deployment_name: t.b.a., defaults to None - :type deployment_name: Optional[str], optional - :param system_prompt: System prompt string, defaults to None - :type system_prompt: Optional[str], optional - :param where: A dictionary of key-value pairs to filter the database results., defaults to None - :type where: dict[str, Any], optional - :param api_key: The api key of the custom endpoint, defaults to None - :type api_key: Optional[str], optional - :param endpoint: The api url of the custom endpoint, defaults to None - :type endpoint: Optional[str], optional - :param model_kwargs: A dictionary of key-value pairs to pass to the model, defaults to None - :type model_kwargs: Optional[Dict[str, Any]], optional - :param callbacks: Langchain callback functions to use, defaults to None - :type callbacks: Optional[list], optional - :param query_type: The type of query to use, defaults to None - :type query_type: Optional[str], optional - :param http_client_proxies: The proxy server settings used to create self.http_client, defaults to None - :type http_client_proxies: Optional[Dict | str], optional - :param http_async_client_proxies: The proxy server settings for async calls used to create - self.http_async_client, defaults to None - :type http_async_client_proxies: Optional[Dict | str], optional - :param local: If True, the model will be run locally, defaults to False (for huggingface provider) - :type local: Optional[bool], optional - :param default_headers: Set additional HTTP headers to be sent with requests to OpenAI - :type default_headers: Optional[Mapping[str, str]], optional - :raises ValueError: If the template is not valid as template should - contain $context and $query (and optionally $history) - :raises ValueError: Stream is not boolean - """ - if template is not None: - logger.warning( - "The `template` argument is deprecated and will be removed in a future version. " - + "Please use `prompt` instead." - ) - if prompt is None: - prompt = template - - if prompt is None: - prompt = DEFAULT_PROMPT_TEMPLATE - - self.number_documents = number_documents - self.temperature = temperature - self.max_tokens = max_tokens - self.model = model - self.top_p = top_p - self.online = online - self.token_usage = token_usage - self.deployment_name = deployment_name - self.system_prompt = system_prompt - self.query_type = query_type - self.callbacks = callbacks - self.api_key = api_key - self.base_url = base_url - self.endpoint = endpoint - self.model_kwargs = model_kwargs - self.http_client = httpx.Client(proxies=http_client_proxies) if http_client_proxies else None - self.http_async_client = ( - httpx.AsyncClient(proxies=http_async_client_proxies) if http_async_client_proxies else None - ) - self.local = local - self.default_headers = default_headers - self.online = online - self.api_version = api_version - - if token_usage: - f = Path(__file__).resolve().parent.parent / "model_prices_and_context_window.json" - self.model_pricing_map = json.load(f.open()) - - if isinstance(prompt, str): - prompt = Template(prompt) - - if self.validate_prompt(prompt): - self.prompt = prompt - else: - raise ValueError("The 'prompt' should have 'query' and 'context' keys and potentially 'history' (if used).") - - if not isinstance(stream, bool): - raise ValueError("`stream` should be bool") - self.stream = stream - self.where = where - - @staticmethod - def validate_prompt(prompt: Template) -> Optional[re.Match[str]]: - """ - validate the prompt - - :param prompt: the prompt to validate - :type prompt: Template - :return: valid (true) or invalid (false) - :rtype: Optional[re.Match[str]] - """ - return re.search(query_re, prompt.template) and re.search(context_re, prompt.template) - - @staticmethod - def _validate_prompt_history(prompt: Template) -> Optional[re.Match[str]]: - """ - validate the prompt with history - - :param prompt: the prompt to validate - :type prompt: Template - :return: valid (true) or invalid (false) - :rtype: Optional[re.Match[str]] - """ - return re.search(history_re, prompt.template) diff --git a/embedchain/embedchain/config/mem0_config.py b/embedchain/embedchain/config/mem0_config.py deleted file mode 100644 index 924ba8744..000000000 --- a/embedchain/embedchain/config/mem0_config.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Any, Optional - -from embedchain.config.base_config import BaseConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class Mem0Config(BaseConfig): - def __init__(self, api_key: str, top_k: Optional[int] = 10): - self.api_key = api_key - self.top_k = top_k - - @staticmethod - def from_config(config: Optional[dict[str, Any]]): - if config is None: - return Mem0Config() - else: - return Mem0Config( - api_key=config.get("api_key", ""), - init_config=config.get("top_k", 10), - ) diff --git a/embedchain/embedchain/config/model_prices_and_context_window.json b/embedchain/embedchain/config/model_prices_and_context_window.json deleted file mode 100644 index c68f90394..000000000 --- a/embedchain/embedchain/config/model_prices_and_context_window.json +++ /dev/null @@ -1,824 +0,0 @@ -{ - "openai/gpt-4": { - "max_tokens": 4096, - "max_input_tokens": 8192, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00003, - "output_cost_per_token": 0.00006 - }, - "openai/gpt-4o": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000005, - "output_cost_per_token": 0.000015 - }, - "openai/gpt-4o-mini": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00000015, - "output_cost_per_token": 0.00000060 - }, - "openai/gpt-4o-mini-2024-07-18": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00000015, - "output_cost_per_token": 0.00000060 - }, - "openai/gpt-4o-2024-05-13": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000005, - "output_cost_per_token": 0.000015 - }, - "openai/gpt-4-turbo-preview": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00001, - "output_cost_per_token": 0.00003 - }, - "openai/gpt-4-0314": { - "max_tokens": 4096, - "max_input_tokens": 8192, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00003, - "output_cost_per_token": 0.00006 - }, - "openai/gpt-4-0613": { - "max_tokens": 4096, - "max_input_tokens": 8192, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00003, - "output_cost_per_token": 0.00006 - }, - "openai/gpt-4-32k": { - "max_tokens": 4096, - "max_input_tokens": 32768, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00006, - "output_cost_per_token": 0.00012 - }, - "openai/gpt-4-32k-0314": { - "max_tokens": 4096, - "max_input_tokens": 32768, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00006, - "output_cost_per_token": 0.00012 - }, - "openai/gpt-4-32k-0613": { - "max_tokens": 4096, - "max_input_tokens": 32768, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00006, - "output_cost_per_token": 0.00012 - }, - "openai/gpt-4-turbo": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00001, - "output_cost_per_token": 0.00003 - }, - "openai/gpt-4-turbo-2024-04-09": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00001, - "output_cost_per_token": 0.00003 - }, - "openai/gpt-4-1106-preview": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00001, - "output_cost_per_token": 0.00003 - }, - "openai/gpt-4-0125-preview": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00001, - "output_cost_per_token": 0.00003 - }, - "openai/gpt-3.5-turbo": { - "max_tokens": 4097, - "max_input_tokens": 16385, - "max_output_tokens": 4096, - "input_cost_per_token": 0.0000015, - "output_cost_per_token": 0.000002 - }, - "openai/gpt-3.5-turbo-0301": { - "max_tokens": 4097, - "max_input_tokens": 4097, - "max_output_tokens": 4096, - "input_cost_per_token": 0.0000015, - "output_cost_per_token": 0.000002 - }, - "openai/gpt-3.5-turbo-0613": { - "input_cost_per_token": 0.0000015, - "output_cost_per_token": 0.000002 - }, - "openai/gpt-3.5-turbo-1106": { - "max_tokens": 16385, - "max_input_tokens": 16385, - "max_output_tokens": 4096, - "input_cost_per_token": 0.0000010, - "output_cost_per_token": 0.0000020 - }, - "openai/gpt-3.5-turbo-0125": { - "max_tokens": 16385, - "max_input_tokens": 16385, - "max_output_tokens": 4096, - "input_cost_per_token": 0.0000005, - "output_cost_per_token": 0.0000015 - }, - "openai/gpt-3.5-turbo-16k": { - "max_tokens": 16385, - "max_input_tokens": 16385, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000003, - "output_cost_per_token": 0.000004 - }, - "openai/gpt-3.5-turbo-16k-0613": { - "max_tokens": 16385, - "max_input_tokens": 16385, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000003, - "output_cost_per_token": 0.000004 - }, - "openai/text-embedding-3-large": { - "max_tokens": 8191, - "max_input_tokens": 8191, - "output_vector_size": 3072, - "input_cost_per_token": 0.00000013, - "output_cost_per_token": 0.000000 - }, - "openai/text-embedding-3-small": { - "max_tokens": 8191, - "max_input_tokens": 8191, - "output_vector_size": 1536, - "input_cost_per_token": 0.00000002, - "output_cost_per_token": 0.000000 - }, - "openai/text-embedding-ada-002": { - "max_tokens": 8191, - "max_input_tokens": 8191, - "output_vector_size": 1536, - "input_cost_per_token": 0.0000001, - "output_cost_per_token": 0.000000 - }, - "openai/text-embedding-ada-002-v2": { - "max_tokens": 8191, - "max_input_tokens": 8191, - "input_cost_per_token": 0.0000001, - "output_cost_per_token": 0.000000 - }, - "openai/babbage-002": { - "max_tokens": 16384, - "max_input_tokens": 16384, - "max_output_tokens": 4096, - "input_cost_per_token": 0.0000004, - "output_cost_per_token": 0.0000004 - }, - "openai/davinci-002": { - "max_tokens": 16384, - "max_input_tokens": 16384, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000002, - "output_cost_per_token": 0.000002 - }, - "openai/gpt-3.5-turbo-instruct": { - "max_tokens": 4096, - "max_input_tokens": 8192, - "max_output_tokens": 4096, - "input_cost_per_token": 0.0000015, - "output_cost_per_token": 0.000002 - }, - "openai/gpt-3.5-turbo-instruct-0914": { - "max_tokens": 4097, - "max_input_tokens": 8192, - "max_output_tokens": 4097, - "input_cost_per_token": 0.0000015, - "output_cost_per_token": 0.000002 - }, - "azure/gpt-4o": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000005, - "output_cost_per_token": 0.000015 - }, - "azure/gpt-4o-mini": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00000015, - "output_cost_per_token": 0.00000060 - }, - "azure/gpt-4-turbo-2024-04-09": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00001, - "output_cost_per_token": 0.00003 - }, - "azure/gpt-4-0125-preview": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00001, - "output_cost_per_token": 0.00003 - }, - "azure/gpt-4-1106-preview": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00001, - "output_cost_per_token": 0.00003 - }, - "azure/gpt-4-0613": { - "max_tokens": 4096, - "max_input_tokens": 8192, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00003, - "output_cost_per_token": 0.00006 - }, - "azure/gpt-4-32k-0613": { - "max_tokens": 4096, - "max_input_tokens": 32768, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00006, - "output_cost_per_token": 0.00012 - }, - "azure/gpt-4-32k": { - "max_tokens": 4096, - "max_input_tokens": 32768, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00006, - "output_cost_per_token": 0.00012 - }, - "azure/gpt-4": { - "max_tokens": 4096, - "max_input_tokens": 8192, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00003, - "output_cost_per_token": 0.00006 - }, - "azure/gpt-4-turbo": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00001, - "output_cost_per_token": 0.00003 - }, - "azure/gpt-4-turbo-vision-preview": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00001, - "output_cost_per_token": 0.00003 - }, - "azure/gpt-3.5-turbo-16k-0613": { - "max_tokens": 4096, - "max_input_tokens": 16385, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000003, - "output_cost_per_token": 0.000004 - }, - "azure/gpt-3.5-turbo-1106": { - "max_tokens": 4096, - "max_input_tokens": 16384, - "max_output_tokens": 4096, - "input_cost_per_token": 0.0000015, - "output_cost_per_token": 0.000002 - }, - "azure/gpt-3.5-turbo-0125": { - "max_tokens": 4096, - "max_input_tokens": 16384, - "max_output_tokens": 4096, - "input_cost_per_token": 0.0000005, - "output_cost_per_token": 0.0000015 - }, - "azure/gpt-3.5-turbo-16k": { - "max_tokens": 4096, - "max_input_tokens": 16385, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000003, - "output_cost_per_token": 0.000004 - }, - "azure/gpt-3.5-turbo": { - "max_tokens": 4096, - "max_input_tokens": 4097, - "max_output_tokens": 4096, - "input_cost_per_token": 0.0000005, - "output_cost_per_token": 0.0000015 - }, - "azure/gpt-3.5-turbo-instruct-0914": { - "max_tokens": 4097, - "max_input_tokens": 4097, - "input_cost_per_token": 0.0000015, - "output_cost_per_token": 0.000002 - }, - "azure/gpt-3.5-turbo-instruct": { - "max_tokens": 4097, - "max_input_tokens": 4097, - "input_cost_per_token": 0.0000015, - "output_cost_per_token": 0.000002 - }, - "azure/text-embedding-ada-002": { - "max_tokens": 8191, - "max_input_tokens": 8191, - "input_cost_per_token": 0.0000001, - "output_cost_per_token": 0.000000 - }, - "azure/text-embedding-3-large": { - "max_tokens": 8191, - "max_input_tokens": 8191, - "input_cost_per_token": 0.00000013, - "output_cost_per_token": 0.000000 - }, - "azure/text-embedding-3-small": { - "max_tokens": 8191, - "max_input_tokens": 8191, - "input_cost_per_token": 0.00000002, - "output_cost_per_token": 0.000000 - }, - "mistralai/mistral-tiny": { - "max_tokens": 8191, - "max_input_tokens": 32000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.00000025, - "output_cost_per_token": 0.00000025 - }, - "mistralai/mistral-small": { - "max_tokens": 8191, - "max_input_tokens": 32000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.000001, - "output_cost_per_token": 0.000003 - }, - "mistralai/mistral-small-latest": { - "max_tokens": 8191, - "max_input_tokens": 32000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.000001, - "output_cost_per_token": 0.000003 - }, - "mistralai/mistral-medium": { - "max_tokens": 8191, - "max_input_tokens": 32000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.0000027, - "output_cost_per_token": 0.0000081 - }, - "mistralai/mistral-medium-latest": { - "max_tokens": 8191, - "max_input_tokens": 32000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.0000027, - "output_cost_per_token": 0.0000081 - }, - "mistralai/mistral-medium-2312": { - "max_tokens": 8191, - "max_input_tokens": 32000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.0000027, - "output_cost_per_token": 0.0000081 - }, - "mistralai/mistral-large-latest": { - "max_tokens": 8191, - "max_input_tokens": 32000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.000004, - "output_cost_per_token": 0.000012 - }, - "mistralai/mistral-large-2402": { - "max_tokens": 8191, - "max_input_tokens": 32000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.000004, - "output_cost_per_token": 0.000012 - }, - "mistralai/open-mistral-7b": { - "max_tokens": 8191, - "max_input_tokens": 32000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.00000025, - "output_cost_per_token": 0.00000025 - }, - "mistralai/open-mixtral-8x7b": { - "max_tokens": 8191, - "max_input_tokens": 32000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.0000007, - "output_cost_per_token": 0.0000007 - }, - "mistralai/open-mixtral-8x22b": { - "max_tokens": 8191, - "max_input_tokens": 64000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.000002, - "output_cost_per_token": 0.000006 - }, - "mistralai/codestral-latest": { - "max_tokens": 8191, - "max_input_tokens": 32000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.000001, - "output_cost_per_token": 0.000003 - }, - "mistralai/codestral-2405": { - "max_tokens": 8191, - "max_input_tokens": 32000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.000001, - "output_cost_per_token": 0.000003 - }, - "mistralai/mistral-embed": { - "max_tokens": 8192, - "max_input_tokens": 8192, - "input_cost_per_token": 0.0000001, - "output_cost_per_token": 0.0 - }, - "groq/llama2-70b-4096": { - "max_tokens": 4096, - "max_input_tokens": 4096, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00000070, - "output_cost_per_token": 0.00000080 - }, - "groq/llama3-8b-8192": { - "max_tokens": 8192, - "max_input_tokens": 8192, - "max_output_tokens": 8192, - "input_cost_per_token": 0.00000010, - "output_cost_per_token": 0.00000010 - }, - "groq/llama3-70b-8192": { - "max_tokens": 8192, - "max_input_tokens": 8192, - "max_output_tokens": 8192, - "input_cost_per_token": 0.00000064, - "output_cost_per_token": 0.00000080 - }, - "groq/mixtral-8x7b-32768": { - "max_tokens": 32768, - "max_input_tokens": 32768, - "max_output_tokens": 32768, - "input_cost_per_token": 0.00000027, - "output_cost_per_token": 0.00000027 - }, - "groq/gemma-7b-it": { - "max_tokens": 8192, - "max_input_tokens": 8192, - "max_output_tokens": 8192, - "input_cost_per_token": 0.00000010, - "output_cost_per_token": 0.00000010 - }, - "anthropic/claude-instant-1": { - "max_tokens": 8191, - "max_input_tokens": 100000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.00000163, - "output_cost_per_token": 0.00000551 - }, - "anthropic/claude-instant-1.2": { - "max_tokens": 8191, - "max_input_tokens": 100000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.000000163, - "output_cost_per_token": 0.000000551 - }, - "anthropic/claude-2": { - "max_tokens": 8191, - "max_input_tokens": 100000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.000008, - "output_cost_per_token": 0.000024 - }, - "anthropic/claude-2.1": { - "max_tokens": 8191, - "max_input_tokens": 200000, - "max_output_tokens": 8191, - "input_cost_per_token": 0.000008, - "output_cost_per_token": 0.000024 - }, - "anthropic/claude-3-haiku-20240307": { - "max_tokens": 4096, - "max_input_tokens": 200000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00000025, - "output_cost_per_token": 0.00000125 - }, - "anthropic/claude-3-opus-20240229": { - "max_tokens": 4096, - "max_input_tokens": 200000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000015, - "output_cost_per_token": 0.000075 - }, - "anthropic/claude-3-sonnet-20240229": { - "max_tokens": 4096, - "max_input_tokens": 200000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000003, - "output_cost_per_token": 0.000015 - }, - "vertexai/chat-bison": { - "max_tokens": 4096, - "max_input_tokens": 8192, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000000125, - "output_cost_per_token": 0.000000125 - }, - "vertexai/chat-bison@001": { - "max_tokens": 4096, - "max_input_tokens": 8192, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000000125, - "output_cost_per_token": 0.000000125 - }, - "vertexai/chat-bison@002": { - "max_tokens": 4096, - "max_input_tokens": 8192, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000000125, - "output_cost_per_token": 0.000000125 - }, - "vertexai/chat-bison-32k": { - "max_tokens": 8192, - "max_input_tokens": 32000, - "max_output_tokens": 8192, - "input_cost_per_token": 0.000000125, - "output_cost_per_token": 0.000000125 - }, - "vertexai/code-bison": { - "max_tokens": 1024, - "max_input_tokens": 6144, - "max_output_tokens": 1024, - "input_cost_per_token": 0.000000125, - "output_cost_per_token": 0.000000125 - }, - "vertexai/code-bison@001": { - "max_tokens": 1024, - "max_input_tokens": 6144, - "max_output_tokens": 1024, - "input_cost_per_token": 0.000000125, - "output_cost_per_token": 0.000000125 - }, - "vertexai/code-gecko@001": { - "max_tokens": 64, - "max_input_tokens": 2048, - "max_output_tokens": 64, - "input_cost_per_token": 0.000000125, - "output_cost_per_token": 0.000000125 - }, - "vertexai/code-gecko@002": { - "max_tokens": 64, - "max_input_tokens": 2048, - "max_output_tokens": 64, - "input_cost_per_token": 0.000000125, - "output_cost_per_token": 0.000000125 - }, - "vertexai/code-gecko": { - "max_tokens": 64, - "max_input_tokens": 2048, - "max_output_tokens": 64, - "input_cost_per_token": 0.000000125, - "output_cost_per_token": 0.000000125 - }, - "vertexai/codechat-bison": { - "max_tokens": 1024, - "max_input_tokens": 6144, - "max_output_tokens": 1024, - "input_cost_per_token": 0.000000125, - "output_cost_per_token": 0.000000125 - }, - "vertexai/codechat-bison@001": { - "max_tokens": 1024, - "max_input_tokens": 6144, - "max_output_tokens": 1024, - "input_cost_per_token": 0.000000125, - "output_cost_per_token": 0.000000125 - }, - "vertexai/codechat-bison-32k": { - "max_tokens": 8192, - "max_input_tokens": 32000, - "max_output_tokens": 8192, - "input_cost_per_token": 0.000000125, - "output_cost_per_token": 0.000000125 - }, - "vertexai/gemini-pro": { - "max_tokens": 8192, - "max_input_tokens": 32760, - "max_output_tokens": 8192, - "input_cost_per_token": 0.00000025, - "output_cost_per_token": 0.0000005 - }, - "vertexai/gemini-1.0-pro": { - "max_tokens": 8192, - "max_input_tokens": 32760, - "max_output_tokens": 8192, - "input_cost_per_token": 0.00000025, - "output_cost_per_token": 0.0000005 - }, - "vertexai/gemini-1.0-pro-001": { - "max_tokens": 8192, - "max_input_tokens": 32760, - "max_output_tokens": 8192, - "input_cost_per_token": 0.00000025, - "output_cost_per_token": 0.0000005 - }, - "vertexai/gemini-1.0-pro-002": { - "max_tokens": 8192, - "max_input_tokens": 32760, - "max_output_tokens": 8192, - "input_cost_per_token": 0.00000025, - "output_cost_per_token": 0.0000005 - }, - "vertexai/gemini-1.5-pro": { - "max_tokens": 8192, - "max_input_tokens": 1000000, - "max_output_tokens": 8192, - "input_cost_per_token": 0.000000625, - "output_cost_per_token": 0.000001875 - }, - "vertexai/gemini-1.5-flash-001": { - "max_tokens": 8192, - "max_input_tokens": 1000000, - "max_output_tokens": 8192, - "input_cost_per_token": 0, - "output_cost_per_token": 0 - }, - "vertexai/gemini-1.5-flash-preview-0514": { - "max_tokens": 8192, - "max_input_tokens": 1000000, - "max_output_tokens": 8192, - "input_cost_per_token": 0, - "output_cost_per_token": 0 - }, - "vertexai/gemini-1.5-pro-001": { - "max_tokens": 8192, - "max_input_tokens": 1000000, - "max_output_tokens": 8192, - "input_cost_per_token": 0.000000625, - "output_cost_per_token": 0.000001875 - }, - "vertexai/gemini-1.5-pro-preview-0514": { - "max_tokens": 8192, - "max_input_tokens": 1000000, - "max_output_tokens": 8192, - "input_cost_per_token": 0.000000625, - "output_cost_per_token": 0.000001875 - }, - "vertexai/gemini-1.5-pro-preview-0215": { - "max_tokens": 8192, - "max_input_tokens": 1000000, - "max_output_tokens": 8192, - "input_cost_per_token": 0.000000625, - "output_cost_per_token": 0.000001875 - }, - "vertexai/gemini-1.5-pro-preview-0409": { - "max_tokens": 8192, - "max_input_tokens": 1000000, - "max_output_tokens": 8192, - "input_cost_per_token": 0.000000625, - "output_cost_per_token": 0.000001875 - }, - "vertexai/gemini-experimental": { - "max_tokens": 8192, - "max_input_tokens": 1000000, - "max_output_tokens": 8192, - "input_cost_per_token": 0, - "output_cost_per_token": 0 - }, - "vertexai/gemini-pro-vision": { - "max_tokens": 2048, - "max_input_tokens": 16384, - "max_output_tokens": 2048, - "max_images_per_prompt": 16, - "max_videos_per_prompt": 1, - "max_video_length": 2, - "input_cost_per_token": 0.00000025, - "output_cost_per_token": 0.0000005 - }, - "vertexai/gemini-1.0-pro-vision": { - "max_tokens": 2048, - "max_input_tokens": 16384, - "max_output_tokens": 2048, - "max_images_per_prompt": 16, - "max_videos_per_prompt": 1, - "max_video_length": 2, - "input_cost_per_token": 0.00000025, - "output_cost_per_token": 0.0000005 - }, - "vertexai/gemini-1.0-pro-vision-001": { - "max_tokens": 2048, - "max_input_tokens": 16384, - "max_output_tokens": 2048, - "max_images_per_prompt": 16, - "max_videos_per_prompt": 1, - "max_video_length": 2, - "input_cost_per_token": 0.00000025, - "output_cost_per_token": 0.0000005 - }, - "vertexai/claude-3-sonnet@20240229": { - "max_tokens": 4096, - "max_input_tokens": 200000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000003, - "output_cost_per_token": 0.000015 - }, - "vertexai/claude-3-haiku@20240307": { - "max_tokens": 4096, - "max_input_tokens": 200000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00000025, - "output_cost_per_token": 0.00000125 - }, - "vertexai/claude-3-opus@20240229": { - "max_tokens": 4096, - "max_input_tokens": 200000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000015, - "output_cost_per_token": 0.000075 - }, - "cohere/command-r": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.00000050, - "output_cost_per_token": 0.0000015 - }, - "cohere/command-light": { - "max_tokens": 4096, - "max_input_tokens": 4096, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000015, - "output_cost_per_token": 0.000015 - }, - "cohere/command-r-plus": { - "max_tokens": 4096, - "max_input_tokens": 128000, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000003, - "output_cost_per_token": 0.000015 - }, - "cohere/command-nightly": { - "max_tokens": 4096, - "max_input_tokens": 4096, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000015, - "output_cost_per_token": 0.000015 - }, - "cohere/command": { - "max_tokens": 4096, - "max_input_tokens": 4096, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000015, - "output_cost_per_token": 0.000015 - }, - "cohere/command-medium-beta": { - "max_tokens": 4096, - "max_input_tokens": 4096, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000015, - "output_cost_per_token": 0.000015 - }, - "cohere/command-xlarge-beta": { - "max_tokens": 4096, - "max_input_tokens": 4096, - "max_output_tokens": 4096, - "input_cost_per_token": 0.000015, - "output_cost_per_token": 0.000015 - }, - "together/together-ai-up-to-3b": { - "input_cost_per_token": 0.0000001, - "output_cost_per_token": 0.0000001 - }, - "together/together-ai-3.1b-7b": { - "input_cost_per_token": 0.0000002, - "output_cost_per_token": 0.0000002 - }, - "together/together-ai-7.1b-20b": { - "max_tokens": 1000, - "input_cost_per_token": 0.0000004, - "output_cost_per_token": 0.0000004 - }, - "together/together-ai-20.1b-40b": { - "input_cost_per_token": 0.0000008, - "output_cost_per_token": 0.0000008 - }, - "together/together-ai-40.1b-70b": { - "input_cost_per_token": 0.0000009, - "output_cost_per_token": 0.0000009 - }, - "together/mistralai/Mixtral-8x7B-Instruct-v0.1": { - "input_cost_per_token": 0.0000006, - "output_cost_per_token": 0.0000006 - } -} \ No newline at end of file diff --git a/embedchain/embedchain/config/vector_db/base.py b/embedchain/embedchain/config/vector_db/base.py deleted file mode 100644 index 3252880a9..000000000 --- a/embedchain/embedchain/config/vector_db/base.py +++ /dev/null @@ -1,36 +0,0 @@ -from typing import Optional - -from embedchain.config.base_config import BaseConfig - - -class BaseVectorDbConfig(BaseConfig): - def __init__( - self, - collection_name: Optional[str] = None, - dir: str = "db", - host: Optional[str] = None, - port: Optional[str] = None, - **kwargs, - ): - """ - Initializes a configuration class instance for the vector database. - - :param collection_name: Default name for the collection, defaults to None - :type collection_name: Optional[str], optional - :param dir: Path to the database directory, where the database is stored, defaults to "db" - :type dir: str, optional - :param host: Database connection remote host. Use this if you run Embedchain as a client, defaults to None - :type host: Optional[str], optional - :param host: Database connection remote port. Use this if you run Embedchain as a client, defaults to None - :type port: Optional[str], optional - :param kwargs: Additional keyword arguments - :type kwargs: dict - """ - self.collection_name = collection_name or "embedchain_store" - self.dir = dir - self.host = host - self.port = port - # Assign additional keyword arguments - if kwargs: - for key, value in kwargs.items(): - setattr(self, key, value) diff --git a/embedchain/embedchain/config/vector_db/chroma.py b/embedchain/embedchain/config/vector_db/chroma.py deleted file mode 100644 index 64220165c..000000000 --- a/embedchain/embedchain/config/vector_db/chroma.py +++ /dev/null @@ -1,41 +0,0 @@ -from typing import Optional - -from embedchain.config.vector_db.base import BaseVectorDbConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class ChromaDbConfig(BaseVectorDbConfig): - def __init__( - self, - collection_name: Optional[str] = None, - dir: Optional[str] = None, - host: Optional[str] = None, - port: Optional[str] = None, - batch_size: Optional[int] = 100, - allow_reset=False, - chroma_settings: Optional[dict] = None, - ): - """ - Initializes a configuration class instance for ChromaDB. - - :param collection_name: Default name for the collection, defaults to None - :type collection_name: Optional[str], optional - :param dir: Path to the database directory, where the database is stored, defaults to None - :type dir: Optional[str], optional - :param host: Database connection remote host. Use this if you run Embedchain as a client, defaults to None - :type host: Optional[str], optional - :param port: Database connection remote port. Use this if you run Embedchain as a client, defaults to None - :type port: Optional[str], optional - :param batch_size: Number of items to insert in one batch, defaults to 100 - :type batch_size: Optional[int], optional - :param allow_reset: Resets the database. defaults to False - :type allow_reset: bool - :param chroma_settings: Chroma settings dict, defaults to None - :type chroma_settings: Optional[dict], optional - """ - - self.chroma_settings = chroma_settings - self.allow_reset = allow_reset - self.batch_size = batch_size - super().__init__(collection_name=collection_name, dir=dir, host=host, port=port) diff --git a/embedchain/embedchain/config/vector_db/elasticsearch.py b/embedchain/embedchain/config/vector_db/elasticsearch.py deleted file mode 100644 index 5e8ef6b61..000000000 --- a/embedchain/embedchain/config/vector_db/elasticsearch.py +++ /dev/null @@ -1,56 +0,0 @@ -import os -from typing import Optional, Union - -from embedchain.config.vector_db.base import BaseVectorDbConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class ElasticsearchDBConfig(BaseVectorDbConfig): - def __init__( - self, - collection_name: Optional[str] = None, - dir: Optional[str] = None, - es_url: Union[str, list[str]] = None, - cloud_id: Optional[str] = None, - batch_size: Optional[int] = 100, - **ES_EXTRA_PARAMS: dict[str, any], - ): - """ - Initializes a configuration class instance for an Elasticsearch client. - - :param collection_name: Default name for the collection, defaults to None - :type collection_name: Optional[str], optional - :param dir: Path to the database directory, where the database is stored, defaults to None - :type dir: Optional[str], optional - :param es_url: elasticsearch url or list of nodes url to be used for connection, defaults to None - :type es_url: Union[str, list[str]], optional - :param cloud_id: cloud id of the elasticsearch cluster, defaults to None - :type cloud_id: Optional[str], optional - :param batch_size: Number of items to insert in one batch, defaults to 100 - :type batch_size: Optional[int], optional - :param ES_EXTRA_PARAMS: extra params dict that can be passed to elasticsearch. - :type ES_EXTRA_PARAMS: dict[str, Any], optional - """ - if es_url and cloud_id: - raise ValueError("Only one of `es_url` and `cloud_id` can be set.") - # self, es_url: Union[str, list[str]] = None, **ES_EXTRA_PARAMS: dict[str, any]): - self.ES_URL = es_url or os.environ.get("ELASTICSEARCH_URL") - self.CLOUD_ID = cloud_id or os.environ.get("ELASTICSEARCH_CLOUD_ID") - if not self.ES_URL and not self.CLOUD_ID: - raise AttributeError( - "Elasticsearch needs a URL or CLOUD_ID attribute, " - "this can either be passed to `ElasticsearchDBConfig` or as `ELASTICSEARCH_URL` or `ELASTICSEARCH_CLOUD_ID` in `.env`" # noqa: E501 - ) - self.ES_EXTRA_PARAMS = ES_EXTRA_PARAMS - # Load API key from .env if it's not explicitly passed. - # Can only set one of 'api_key', 'basic_auth', and 'bearer_auth' - if ( - not self.ES_EXTRA_PARAMS.get("api_key") - and not self.ES_EXTRA_PARAMS.get("basic_auth") - and not self.ES_EXTRA_PARAMS.get("bearer_auth") - ): - self.ES_EXTRA_PARAMS["api_key"] = os.environ.get("ELASTICSEARCH_API_KEY") - - self.batch_size = batch_size - super().__init__(collection_name=collection_name, dir=dir) diff --git a/embedchain/embedchain/config/vector_db/lancedb.py b/embedchain/embedchain/config/vector_db/lancedb.py deleted file mode 100644 index 08b7d0ac7..000000000 --- a/embedchain/embedchain/config/vector_db/lancedb.py +++ /dev/null @@ -1,33 +0,0 @@ -from typing import Optional - -from embedchain.config.vector_db.base import BaseVectorDbConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class LanceDBConfig(BaseVectorDbConfig): - def __init__( - self, - collection_name: Optional[str] = None, - dir: Optional[str] = None, - host: Optional[str] = None, - port: Optional[str] = None, - allow_reset=True, - ): - """ - Initializes a configuration class instance for LanceDB. - - :param collection_name: Default name for the collection, defaults to None - :type collection_name: Optional[str], optional - :param dir: Path to the database directory, where the database is stored, defaults to None - :type dir: Optional[str], optional - :param host: Database connection remote host. Use this if you run Embedchain as a client, defaults to None - :type host: Optional[str], optional - :param port: Database connection remote port. Use this if you run Embedchain as a client, defaults to None - :type port: Optional[str], optional - :param allow_reset: Resets the database. defaults to False - :type allow_reset: bool - """ - - self.allow_reset = allow_reset - super().__init__(collection_name=collection_name, dir=dir, host=host, port=port) diff --git a/embedchain/embedchain/config/vector_db/opensearch.py b/embedchain/embedchain/config/vector_db/opensearch.py deleted file mode 100644 index 5beeb8cee..000000000 --- a/embedchain/embedchain/config/vector_db/opensearch.py +++ /dev/null @@ -1,41 +0,0 @@ -from typing import Optional - -from embedchain.config.vector_db.base import BaseVectorDbConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class OpenSearchDBConfig(BaseVectorDbConfig): - def __init__( - self, - opensearch_url: str, - http_auth: tuple[str, str], - vector_dimension: int = 1536, - collection_name: Optional[str] = None, - dir: Optional[str] = None, - batch_size: Optional[int] = 100, - **extra_params: dict[str, any], - ): - """ - Initializes a configuration class instance for an OpenSearch client. - - :param collection_name: Default name for the collection, defaults to None - :type collection_name: Optional[str], optional - :param opensearch_url: URL of the OpenSearch domain - :type opensearch_url: str, Eg, "http://localhost:9200" - :param http_auth: Tuple of username and password - :type http_auth: tuple[str, str], Eg, ("username", "password") - :param vector_dimension: Dimension of the vector, defaults to 1536 (openai embedding model) - :type vector_dimension: int, optional - :param dir: Path to the database directory, where the database is stored, defaults to None - :type dir: Optional[str], optional - :param batch_size: Number of items to insert in one batch, defaults to 100 - :type batch_size: Optional[int], optional - """ - self.opensearch_url = opensearch_url - self.http_auth = http_auth - self.vector_dimension = vector_dimension - self.extra_params = extra_params - self.batch_size = batch_size - - super().__init__(collection_name=collection_name, dir=dir) diff --git a/embedchain/embedchain/config/vector_db/pinecone.py b/embedchain/embedchain/config/vector_db/pinecone.py deleted file mode 100644 index 83248579f..000000000 --- a/embedchain/embedchain/config/vector_db/pinecone.py +++ /dev/null @@ -1,47 +0,0 @@ -import os -from typing import Optional - -from embedchain.config.vector_db.base import BaseVectorDbConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class PineconeDBConfig(BaseVectorDbConfig): - def __init__( - self, - index_name: Optional[str] = None, - api_key: Optional[str] = None, - vector_dimension: int = 1536, - metric: Optional[str] = "cosine", - pod_config: Optional[dict[str, any]] = None, - serverless_config: Optional[dict[str, any]] = None, - hybrid_search: bool = False, - bm25_encoder: any = None, - batch_size: Optional[int] = 100, - **extra_params: dict[str, any], - ): - self.metric = metric - self.api_key = api_key - self.index_name = index_name - self.vector_dimension = vector_dimension - self.extra_params = extra_params - self.hybrid_search = hybrid_search - self.bm25_encoder = bm25_encoder - self.batch_size = batch_size - if pod_config is None and serverless_config is None: - # If no config is provided, use the default pod spec config - pod_environment = os.environ.get("PINECONE_ENV", "gcp-starter") - self.pod_config = {"environment": pod_environment, "metadata_config": {"indexed": ["*"]}} - else: - self.pod_config = pod_config - self.serverless_config = serverless_config - - if self.pod_config and self.serverless_config: - raise ValueError("Only one of pod_config or serverless_config can be provided.") - - if self.hybrid_search and self.metric != "dotproduct": - raise ValueError( - "Hybrid search is only supported with dotproduct metric in Pinecone. See full docs here: https://docs.pinecone.io/docs/hybrid-search#limitations" - ) # noqa:E501 - - super().__init__(collection_name=self.index_name, dir=None) diff --git a/embedchain/embedchain/config/vector_db/qdrant.py b/embedchain/embedchain/config/vector_db/qdrant.py deleted file mode 100644 index acdeacfff..000000000 --- a/embedchain/embedchain/config/vector_db/qdrant.py +++ /dev/null @@ -1,48 +0,0 @@ -from typing import Optional - -from embedchain.config.vector_db.base import BaseVectorDbConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class QdrantDBConfig(BaseVectorDbConfig): - """ - Config to initialize a qdrant client. - :param: url. qdrant url or list of nodes url to be used for connection - """ - - def __init__( - self, - collection_name: Optional[str] = None, - dir: Optional[str] = None, - hnsw_config: Optional[dict[str, any]] = None, - quantization_config: Optional[dict[str, any]] = None, - on_disk: Optional[bool] = None, - batch_size: Optional[int] = 10, - **extra_params: dict[str, any], - ): - """ - Initializes a configuration class instance for a qdrant client. - - :param collection_name: Default name for the collection, defaults to None - :type collection_name: Optional[str], optional - :param dir: Path to the database directory, where the database is stored, defaults to None - :type dir: Optional[str], optional - :param hnsw_config: Params for HNSW index - :type hnsw_config: Optional[dict[str, any]], defaults to None - :param quantization_config: Params for quantization, if None - quantization will be disabled - :type quantization_config: Optional[dict[str, any]], defaults to None - :param on_disk: If true - point`s payload will not be stored in memory. - It will be read from the disk every time it is requested. - This setting saves RAM by (slightly) increasing the response time. - Note: those payload values that are involved in filtering and are indexed - remain in RAM. - :type on_disk: bool, optional, defaults to None - :param batch_size: Number of items to insert in one batch, defaults to 10 - :type batch_size: Optional[int], optional - """ - self.hnsw_config = hnsw_config - self.quantization_config = quantization_config - self.on_disk = on_disk - self.batch_size = batch_size - self.extra_params = extra_params - super().__init__(collection_name=collection_name, dir=dir) diff --git a/embedchain/embedchain/config/vector_db/weaviate.py b/embedchain/embedchain/config/vector_db/weaviate.py deleted file mode 100644 index f40c472e7..000000000 --- a/embedchain/embedchain/config/vector_db/weaviate.py +++ /dev/null @@ -1,18 +0,0 @@ -from typing import Optional - -from embedchain.config.vector_db.base import BaseVectorDbConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class WeaviateDBConfig(BaseVectorDbConfig): - def __init__( - self, - collection_name: Optional[str] = None, - dir: Optional[str] = None, - batch_size: Optional[int] = 100, - **extra_params: dict[str, any], - ): - self.batch_size = batch_size - self.extra_params = extra_params - super().__init__(collection_name=collection_name, dir=dir) diff --git a/embedchain/embedchain/config/vector_db/zilliz.py b/embedchain/embedchain/config/vector_db/zilliz.py deleted file mode 100644 index 268941157..000000000 --- a/embedchain/embedchain/config/vector_db/zilliz.py +++ /dev/null @@ -1,49 +0,0 @@ -import os -from typing import Optional - -from embedchain.config.vector_db.base import BaseVectorDbConfig -from embedchain.helpers.json_serializable import register_deserializable - - -@register_deserializable -class ZillizDBConfig(BaseVectorDbConfig): - def __init__( - self, - collection_name: Optional[str] = None, - dir: Optional[str] = None, - uri: Optional[str] = None, - token: Optional[str] = None, - vector_dim: Optional[str] = None, - metric_type: Optional[str] = None, - ): - """ - Initializes a configuration class instance for the vector database. - - :param collection_name: Default name for the collection, defaults to None - :type collection_name: Optional[str], optional - :param dir: Path to the database directory, where the database is stored, defaults to "db" - :type dir: str, optional - :param uri: Cluster endpoint obtained from the Zilliz Console, defaults to None - :type uri: Optional[str], optional - :param token: API Key, if a Serverless Cluster, username:password, if a Dedicated Cluster, defaults to None - :type token: Optional[str], optional - """ - self.uri = uri or os.environ.get("ZILLIZ_CLOUD_URI") - if not self.uri: - raise AttributeError( - "Zilliz needs a URI attribute, " - "this can either be passed to `ZILLIZ_CLOUD_URI` or as `ZILLIZ_CLOUD_URI` in `.env`" - ) - - self.token = token or os.environ.get("ZILLIZ_CLOUD_TOKEN") - if not self.token: - raise AttributeError( - "Zilliz needs a token attribute, " - "this can either be passed to `ZILLIZ_CLOUD_TOKEN` or as `ZILLIZ_CLOUD_TOKEN` in `.env`," - "if having a username and password, pass it in the form 'username:password' to `ZILLIZ_CLOUD_TOKEN`" - ) - - self.metric_type = metric_type if metric_type else "L2" - - self.vector_dim = vector_dim - super().__init__(collection_name=collection_name, dir=dir) diff --git a/embedchain/embedchain/config/vectordb/__init__.py b/embedchain/embedchain/config/vectordb/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/constants.py b/embedchain/embedchain/constants.py deleted file mode 100644 index d3d7b28b3..000000000 --- a/embedchain/embedchain/constants.py +++ /dev/null @@ -1,11 +0,0 @@ -import os -from pathlib import Path - -ABS_PATH = os.getcwd() -HOME_DIR = os.environ.get("EMBEDCHAIN_CONFIG_DIR", str(Path.home())) -CONFIG_DIR = os.path.join(HOME_DIR, ".embedchain") -CONFIG_FILE = os.path.join(CONFIG_DIR, "config.json") -SQLITE_PATH = os.path.join(CONFIG_DIR, "embedchain.db") - -# Set the environment variable for the database URI -os.environ.setdefault("EMBEDCHAIN_DB_URI", f"sqlite:///{SQLITE_PATH}") diff --git a/embedchain/embedchain/core/__init__.py b/embedchain/embedchain/core/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/core/db/__init__.py b/embedchain/embedchain/core/db/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/core/db/database.py b/embedchain/embedchain/core/db/database.py deleted file mode 100644 index 0965ca8ff..000000000 --- a/embedchain/embedchain/core/db/database.py +++ /dev/null @@ -1,88 +0,0 @@ -import os - -from alembic import command -from alembic.config import Config -from sqlalchemy import create_engine -from sqlalchemy.engine.base import Engine -from sqlalchemy.orm import Session as SQLAlchemySession -from sqlalchemy.orm import scoped_session, sessionmaker - -from .models import Base - - -class DatabaseManager: - def __init__(self, echo: bool = False): - self.database_uri = os.environ.get("EMBEDCHAIN_DB_URI") - self.echo = echo - self.engine: Engine = None - self._session_factory = None - - def setup_engine(self) -> None: - """Initializes the database engine and session factory.""" - if not self.database_uri: - raise RuntimeError("Database URI is not set. Set the EMBEDCHAIN_DB_URI environment variable.") - connect_args = {} - if self.database_uri.startswith("sqlite"): - connect_args["check_same_thread"] = False - self.engine = create_engine(self.database_uri, echo=self.echo, connect_args=connect_args) - self._session_factory = scoped_session(sessionmaker(bind=self.engine)) - Base.metadata.bind = self.engine - - def init_db(self) -> None: - """Creates all tables defined in the Base metadata.""" - if not self.engine: - raise RuntimeError("Database engine is not initialized. Call setup_engine() first.") - Base.metadata.create_all(self.engine) - - def get_session(self) -> SQLAlchemySession: - """Provides a session for database operations.""" - if not self._session_factory: - raise RuntimeError("Session factory is not initialized. Call setup_engine() first.") - return self._session_factory() - - def close_session(self) -> None: - """Closes the current session.""" - if self._session_factory: - self._session_factory.remove() - - def execute_transaction(self, transaction_block): - """Executes a block of code within a database transaction.""" - session = self.get_session() - try: - transaction_block(session) - session.commit() - except Exception as e: - session.rollback() - raise e - finally: - self.close_session() - - -# Singleton pattern to use throughout the application -database_manager = DatabaseManager() - - -# Convenience functions for backward compatibility and ease of use -def setup_engine(database_uri: str, echo: bool = False) -> None: - database_manager.database_uri = database_uri - database_manager.echo = echo - database_manager.setup_engine() - - -def alembic_upgrade() -> None: - """Upgrades the database to the latest version.""" - alembic_config_path = os.path.join(os.path.dirname(__file__), "..", "..", "alembic.ini") - alembic_cfg = Config(alembic_config_path) - command.upgrade(alembic_cfg, "head") - - -def init_db() -> None: - alembic_upgrade() - - -def get_session() -> SQLAlchemySession: - return database_manager.get_session() - - -def execute_transaction(transaction_block): - database_manager.execute_transaction(transaction_block) diff --git a/embedchain/embedchain/core/db/models.py b/embedchain/embedchain/core/db/models.py deleted file mode 100644 index af77803f7..000000000 --- a/embedchain/embedchain/core/db/models.py +++ /dev/null @@ -1,31 +0,0 @@ -import uuid - -from sqlalchemy import TIMESTAMP, Column, Integer, String, Text, func -from sqlalchemy.orm import declarative_base - -Base = declarative_base() -metadata = Base.metadata - - -class DataSource(Base): - __tablename__ = "ec_data_sources" - - id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4())) - app_id = Column(Text, index=True) - hash = Column(Text, index=True) - type = Column(Text, index=True) - value = Column(Text) - meta_data = Column(Text, name="metadata") - is_uploaded = Column(Integer, default=0) - - -class ChatHistory(Base): - __tablename__ = "ec_chat_history" - - app_id = Column(String, primary_key=True) - id = Column(String, primary_key=True) - session_id = Column(String, primary_key=True, index=True) - question = Column(Text) - answer = Column(Text) - meta_data = Column(Text, name="metadata") - created_at = Column(TIMESTAMP, default=func.current_timestamp(), index=True) diff --git a/embedchain/embedchain/data_formatter/__init__.py b/embedchain/embedchain/data_formatter/__init__.py deleted file mode 100644 index 047b8e7ca..000000000 --- a/embedchain/embedchain/data_formatter/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .data_formatter import DataFormatter # noqa: F401 diff --git a/embedchain/embedchain/data_formatter/data_formatter.py b/embedchain/embedchain/data_formatter/data_formatter.py deleted file mode 100644 index 72923888d..000000000 --- a/embedchain/embedchain/data_formatter/data_formatter.py +++ /dev/null @@ -1,154 +0,0 @@ -from importlib import import_module -from typing import Any, Optional - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config import AddConfig -from embedchain.config.add_config import ChunkerConfig, LoaderConfig -from embedchain.helpers.json_serializable import JSONSerializable -from embedchain.loaders.base_loader import BaseLoader -from embedchain.models.data_type import DataType - - -class DataFormatter(JSONSerializable): - """ - DataFormatter is an internal utility class which abstracts the mapping for - loaders and chunkers to the data_type entered by the user in their - .add or .add_local method call - """ - - def __init__( - self, - data_type: DataType, - config: AddConfig, - loader: Optional[BaseLoader] = None, - chunker: Optional[BaseChunker] = None, - ): - """ - Initialize a dataformatter, set data type and chunker based on datatype. - - :param data_type: The type of the data to load and chunk. - :type data_type: DataType - :param config: AddConfig instance with nested loader and chunker config attributes. - :type config: AddConfig - """ - self.loader = self._get_loader(data_type=data_type, config=config.loader, loader=loader) - self.chunker = self._get_chunker(data_type=data_type, config=config.chunker, chunker=chunker) - - @staticmethod - def _lazy_load(module_path: str): - module_path, class_name = module_path.rsplit(".", 1) - module = import_module(module_path) - return getattr(module, class_name) - - def _get_loader( - self, - data_type: DataType, - config: LoaderConfig, - loader: Optional[BaseLoader], - **kwargs: Optional[dict[str, Any]], - ) -> BaseLoader: - """ - Returns the appropriate data loader for the given data type. - - :param data_type: The type of the data to load. - :type data_type: DataType - :param config: Config to initialize the loader with. - :type config: LoaderConfig - :raises ValueError: If an unsupported data type is provided. - :return: The loader for the given data type. - :rtype: BaseLoader - """ - loaders = { - DataType.YOUTUBE_VIDEO: "embedchain.loaders.youtube_video.YoutubeVideoLoader", - DataType.PDF_FILE: "embedchain.loaders.pdf_file.PdfFileLoader", - DataType.WEB_PAGE: "embedchain.loaders.web_page.WebPageLoader", - DataType.QNA_PAIR: "embedchain.loaders.local_qna_pair.LocalQnaPairLoader", - DataType.TEXT: "embedchain.loaders.local_text.LocalTextLoader", - DataType.DOCX: "embedchain.loaders.docx_file.DocxFileLoader", - DataType.SITEMAP: "embedchain.loaders.sitemap.SitemapLoader", - DataType.XML: "embedchain.loaders.xml.XmlLoader", - DataType.DOCS_SITE: "embedchain.loaders.docs_site_loader.DocsSiteLoader", - DataType.CSV: "embedchain.loaders.csv.CsvLoader", - DataType.MDX: "embedchain.loaders.mdx.MdxLoader", - DataType.IMAGE: "embedchain.loaders.image.ImageLoader", - DataType.UNSTRUCTURED: "embedchain.loaders.unstructured_file.UnstructuredLoader", - DataType.JSON: "embedchain.loaders.json.JSONLoader", - DataType.OPENAPI: "embedchain.loaders.openapi.OpenAPILoader", - DataType.GMAIL: "embedchain.loaders.gmail.GmailLoader", - DataType.NOTION: "embedchain.loaders.notion.NotionLoader", - DataType.SUBSTACK: "embedchain.loaders.substack.SubstackLoader", - DataType.YOUTUBE_CHANNEL: "embedchain.loaders.youtube_channel.YoutubeChannelLoader", - DataType.DISCORD: "embedchain.loaders.discord.DiscordLoader", - DataType.RSSFEED: "embedchain.loaders.rss_feed.RSSFeedLoader", - DataType.BEEHIIV: "embedchain.loaders.beehiiv.BeehiivLoader", - DataType.GOOGLE_DRIVE: "embedchain.loaders.google_drive.GoogleDriveLoader", - DataType.DIRECTORY: "embedchain.loaders.directory_loader.DirectoryLoader", - DataType.SLACK: "embedchain.loaders.slack.SlackLoader", - DataType.DROPBOX: "embedchain.loaders.dropbox.DropboxLoader", - DataType.TEXT_FILE: "embedchain.loaders.text_file.TextFileLoader", - DataType.EXCEL_FILE: "embedchain.loaders.excel_file.ExcelFileLoader", - DataType.AUDIO: "embedchain.loaders.audio.AudioLoader", - } - - if data_type == DataType.CUSTOM or loader is not None: - loader_class: type = loader - if loader_class: - return loader_class - elif data_type in loaders: - loader_class: type = self._lazy_load(loaders[data_type]) - return loader_class() - - raise ValueError( - f"Cant find the loader for {data_type}.\ - We recommend to pass the loader to use data_type: {data_type},\ - check `https://docs.embedchain.ai/data-sources/overview`." - ) - - def _get_chunker(self, data_type: DataType, config: ChunkerConfig, chunker: Optional[BaseChunker]) -> BaseChunker: - """Returns the appropriate chunker for the given data type (updated for lazy loading).""" - chunker_classes = { - DataType.YOUTUBE_VIDEO: "embedchain.chunkers.youtube_video.YoutubeVideoChunker", - DataType.PDF_FILE: "embedchain.chunkers.pdf_file.PdfFileChunker", - DataType.WEB_PAGE: "embedchain.chunkers.web_page.WebPageChunker", - DataType.QNA_PAIR: "embedchain.chunkers.qna_pair.QnaPairChunker", - DataType.TEXT: "embedchain.chunkers.text.TextChunker", - DataType.DOCX: "embedchain.chunkers.docx_file.DocxFileChunker", - DataType.SITEMAP: "embedchain.chunkers.sitemap.SitemapChunker", - DataType.XML: "embedchain.chunkers.xml.XmlChunker", - DataType.DOCS_SITE: "embedchain.chunkers.docs_site.DocsSiteChunker", - DataType.CSV: "embedchain.chunkers.table.TableChunker", - DataType.MDX: "embedchain.chunkers.mdx.MdxChunker", - DataType.IMAGE: "embedchain.chunkers.image.ImageChunker", - DataType.UNSTRUCTURED: "embedchain.chunkers.unstructured_file.UnstructuredFileChunker", - DataType.JSON: "embedchain.chunkers.json.JSONChunker", - DataType.OPENAPI: "embedchain.chunkers.openapi.OpenAPIChunker", - DataType.GMAIL: "embedchain.chunkers.gmail.GmailChunker", - DataType.NOTION: "embedchain.chunkers.notion.NotionChunker", - DataType.SUBSTACK: "embedchain.chunkers.substack.SubstackChunker", - DataType.YOUTUBE_CHANNEL: "embedchain.chunkers.common_chunker.CommonChunker", - DataType.DISCORD: "embedchain.chunkers.common_chunker.CommonChunker", - DataType.CUSTOM: "embedchain.chunkers.common_chunker.CommonChunker", - DataType.RSSFEED: "embedchain.chunkers.rss_feed.RSSFeedChunker", - DataType.BEEHIIV: "embedchain.chunkers.beehiiv.BeehiivChunker", - DataType.GOOGLE_DRIVE: "embedchain.chunkers.google_drive.GoogleDriveChunker", - DataType.DIRECTORY: "embedchain.chunkers.common_chunker.CommonChunker", - DataType.SLACK: "embedchain.chunkers.common_chunker.CommonChunker", - DataType.DROPBOX: "embedchain.chunkers.common_chunker.CommonChunker", - DataType.TEXT_FILE: "embedchain.chunkers.common_chunker.CommonChunker", - DataType.EXCEL_FILE: "embedchain.chunkers.excel_file.ExcelFileChunker", - DataType.AUDIO: "embedchain.chunkers.audio.AudioChunker", - } - - if chunker is not None: - return chunker - elif data_type in chunker_classes: - chunker_class = self._lazy_load(chunker_classes[data_type]) - chunker = chunker_class(config) - chunker.set_data_type(data_type) - return chunker - - raise ValueError( - f"Cant find the chunker for {data_type}.\ - We recommend to pass the chunker to use data_type: {data_type},\ - check `https://docs.embedchain.ai/data-sources/overview`." - ) diff --git a/embedchain/embedchain/deployment/fly.io/.dockerignore b/embedchain/embedchain/deployment/fly.io/.dockerignore deleted file mode 100644 index 9f4c740db..000000000 --- a/embedchain/embedchain/deployment/fly.io/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -db/ \ No newline at end of file diff --git a/embedchain/embedchain/deployment/fly.io/.env.example b/embedchain/embedchain/deployment/fly.io/.env.example deleted file mode 100644 index b29363f94..000000000 --- a/embedchain/embedchain/deployment/fly.io/.env.example +++ /dev/null @@ -1 +0,0 @@ -OPENAI_API_KEY=sk-xxx \ No newline at end of file diff --git a/embedchain/embedchain/deployment/fly.io/Dockerfile b/embedchain/embedchain/deployment/fly.io/Dockerfile deleted file mode 100644 index 9eac80cee..000000000 --- a/embedchain/embedchain/deployment/fly.io/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM python:3.11-slim - -WORKDIR /app - -COPY requirements.txt /app/ - -RUN pip install -r requirements.txt - -COPY . /app - -EXPOSE 8080 - -CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"] diff --git a/embedchain/embedchain/deployment/fly.io/app.py b/embedchain/embedchain/deployment/fly.io/app.py deleted file mode 100644 index 003543c46..000000000 --- a/embedchain/embedchain/deployment/fly.io/app.py +++ /dev/null @@ -1,56 +0,0 @@ -from dotenv import load_dotenv -from fastapi import FastAPI, responses -from pydantic import BaseModel - -from embedchain import App - -load_dotenv(".env") - -app = FastAPI(title="Embedchain FastAPI App") -embedchain_app = App() - - -class SourceModel(BaseModel): - source: str - - -class QuestionModel(BaseModel): - question: str - - -@app.post("/add") -async def add_source(source_model: SourceModel): - """ - Adds a new source to the EmbedChain app. - Expects a JSON with a "source" key. - """ - source = source_model.source - embedchain_app.add(source) - return {"message": f"Source '{source}' added successfully."} - - -@app.post("/query") -async def handle_query(question_model: QuestionModel): - """ - Handles a query to the EmbedChain app. - Expects a JSON with a "question" key. - """ - question = question_model.question - answer = embedchain_app.query(question) - return {"answer": answer} - - -@app.post("/chat") -async def handle_chat(question_model: QuestionModel): - """ - Handles a chat request to the EmbedChain app. - Expects a JSON with a "question" key. - """ - question = question_model.question - response = embedchain_app.chat(question) - return {"response": response} - - -@app.get("/") -async def root(): - return responses.RedirectResponse(url="/docs") diff --git a/embedchain/embedchain/deployment/fly.io/requirements.txt b/embedchain/embedchain/deployment/fly.io/requirements.txt deleted file mode 100644 index 3a7689298..000000000 --- a/embedchain/embedchain/deployment/fly.io/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -fastapi==0.104.0 -uvicorn==0.23.2 -embedchain -beautifulsoup4 \ No newline at end of file diff --git a/embedchain/embedchain/deployment/gradio.app/app.py b/embedchain/embedchain/deployment/gradio.app/app.py deleted file mode 100644 index 24a96a908..000000000 --- a/embedchain/embedchain/deployment/gradio.app/app.py +++ /dev/null @@ -1,18 +0,0 @@ -import os - -import gradio as gr - -from embedchain import App - -os.environ["OPENAI_API_KEY"] = "sk-xxx" - -app = App() - - -def query(message, history): - return app.chat(message) - - -demo = gr.ChatInterface(query) - -demo.launch() diff --git a/embedchain/embedchain/deployment/gradio.app/requirements.txt b/embedchain/embedchain/deployment/gradio.app/requirements.txt deleted file mode 100644 index f8b933480..000000000 --- a/embedchain/embedchain/deployment/gradio.app/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -gradio>=4.14.0 -embedchain diff --git a/embedchain/embedchain/deployment/modal.com/.env.example b/embedchain/embedchain/deployment/modal.com/.env.example deleted file mode 100644 index b29363f94..000000000 --- a/embedchain/embedchain/deployment/modal.com/.env.example +++ /dev/null @@ -1 +0,0 @@ -OPENAI_API_KEY=sk-xxx \ No newline at end of file diff --git a/embedchain/embedchain/deployment/modal.com/.gitignore b/embedchain/embedchain/deployment/modal.com/.gitignore deleted file mode 100644 index 4c49bd78f..000000000 --- a/embedchain/embedchain/deployment/modal.com/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.env diff --git a/embedchain/embedchain/deployment/modal.com/app.py b/embedchain/embedchain/deployment/modal.com/app.py deleted file mode 100644 index 1e02aeefb..000000000 --- a/embedchain/embedchain/deployment/modal.com/app.py +++ /dev/null @@ -1,86 +0,0 @@ -from dotenv import load_dotenv -from fastapi import Body, FastAPI, responses -from modal import Image, Secret, Stub, asgi_app - -from embedchain import App - -load_dotenv(".env") - -image = Image.debian_slim().pip_install( - "embedchain", - "lanchain_community==0.2.6", - "youtube-transcript-api==0.6.1", - "pytube==15.0.0", - "beautifulsoup4==4.12.3", - "slack-sdk==3.21.3", - "huggingface_hub==0.23.0", - "gitpython==3.1.38", - "yt_dlp==2023.11.14", - "PyGithub==1.59.1", - "feedparser==6.0.10", - "newspaper3k==0.2.8", - "listparser==0.19", -) - -stub = Stub( - name="embedchain-app", - image=image, - secrets=[Secret.from_dotenv(".env")], -) - -web_app = FastAPI() -embedchain_app = App(name="embedchain-modal-app") - - -@web_app.post("/add") -async def add( - source: str = Body(..., description="Source to be added"), - data_type: str | None = Body(None, description="Type of the data source"), -): - """ - Adds a new source to the EmbedChain app. - Expects a JSON with a "source" and "data_type" key. - "data_type" is optional. - """ - if source and data_type: - embedchain_app.add(source, data_type) - elif source: - embedchain_app.add(source) - else: - return {"message": "No source provided."} - return {"message": f"Source '{source}' added successfully."} - - -@web_app.post("/query") -async def query(question: str = Body(..., description="Question to be answered")): - """ - Handles a query to the EmbedChain app. - Expects a JSON with a "question" key. - """ - if not question: - return {"message": "No question provided."} - answer = embedchain_app.query(question) - return {"answer": answer} - - -@web_app.get("/chat") -async def chat(question: str = Body(..., description="Question to be answered")): - """ - Handles a chat request to the EmbedChain app. - Expects a JSON with a "question" key. - """ - if not question: - return {"message": "No question provided."} - response = embedchain_app.chat(question) - return {"response": response} - - -@web_app.get("/") -async def root(): - return responses.RedirectResponse(url="/docs") - - -@stub.function(image=image) -@asgi_app() -def fastapi_app(): - return web_app diff --git a/embedchain/embedchain/deployment/modal.com/requirements.txt b/embedchain/embedchain/deployment/modal.com/requirements.txt deleted file mode 100644 index 69a3172af..000000000 --- a/embedchain/embedchain/deployment/modal.com/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -modal==0.56.4329 -fastapi==0.104.0 -uvicorn==0.23.2 -embedchain diff --git a/embedchain/embedchain/deployment/render.com/.env.example b/embedchain/embedchain/deployment/render.com/.env.example deleted file mode 100644 index b29363f94..000000000 --- a/embedchain/embedchain/deployment/render.com/.env.example +++ /dev/null @@ -1 +0,0 @@ -OPENAI_API_KEY=sk-xxx \ No newline at end of file diff --git a/embedchain/embedchain/deployment/render.com/.gitignore b/embedchain/embedchain/deployment/render.com/.gitignore deleted file mode 100644 index 4c49bd78f..000000000 --- a/embedchain/embedchain/deployment/render.com/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.env diff --git a/embedchain/embedchain/deployment/render.com/app.py b/embedchain/embedchain/deployment/render.com/app.py deleted file mode 100644 index 00d29bf3d..000000000 --- a/embedchain/embedchain/deployment/render.com/app.py +++ /dev/null @@ -1,53 +0,0 @@ -from fastapi import FastAPI, responses -from pydantic import BaseModel - -from embedchain import App - -app = FastAPI(title="Embedchain FastAPI App") -embedchain_app = App() - - -class SourceModel(BaseModel): - source: str - - -class QuestionModel(BaseModel): - question: str - - -@app.post("/add") -async def add_source(source_model: SourceModel): - """ - Adds a new source to the EmbedChain app. - Expects a JSON with a "source" key. - """ - source = source_model.source - embedchain_app.add(source) - return {"message": f"Source '{source}' added successfully."} - - -@app.post("/query") -async def handle_query(question_model: QuestionModel): - """ - Handles a query to the EmbedChain app. - Expects a JSON with a "question" key. - """ - question = question_model.question - answer = embedchain_app.query(question) - return {"answer": answer} - - -@app.post("/chat") -async def handle_chat(question_model: QuestionModel): - """ - Handles a chat request to the EmbedChain app. - Expects a JSON with a "question" key. - """ - question = question_model.question - response = embedchain_app.chat(question) - return {"response": response} - - -@app.get("/") -async def root(): - return responses.RedirectResponse(url="/docs") diff --git a/embedchain/embedchain/deployment/render.com/render.yaml b/embedchain/embedchain/deployment/render.com/render.yaml deleted file mode 100644 index 04ec5048b..000000000 --- a/embedchain/embedchain/deployment/render.com/render.yaml +++ /dev/null @@ -1,16 +0,0 @@ -services: - - type: web - name: ec-render-app - runtime: python - repo: https://github.com// - scaling: - minInstances: 1 - maxInstances: 3 - targetMemoryPercent: 60 # optional if targetCPUPercent is set - targetCPUPercent: 60 # optional if targetMemory is set - buildCommand: pip install -r requirements.txt - startCommand: uvicorn app:app --host 0.0.0.0 - envVars: - - key: OPENAI_API_KEY - value: sk-xxx - autoDeploy: false # optional diff --git a/embedchain/embedchain/deployment/render.com/requirements.txt b/embedchain/embedchain/deployment/render.com/requirements.txt deleted file mode 100644 index 3a7689298..000000000 --- a/embedchain/embedchain/deployment/render.com/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -fastapi==0.104.0 -uvicorn==0.23.2 -embedchain -beautifulsoup4 \ No newline at end of file diff --git a/embedchain/embedchain/deployment/streamlit.io/.streamlit/secrets.toml b/embedchain/embedchain/deployment/streamlit.io/.streamlit/secrets.toml deleted file mode 100644 index 1fa8f4495..000000000 --- a/embedchain/embedchain/deployment/streamlit.io/.streamlit/secrets.toml +++ /dev/null @@ -1 +0,0 @@ -OPENAI_API_KEY="sk-xxx" diff --git a/embedchain/embedchain/deployment/streamlit.io/app.py b/embedchain/embedchain/deployment/streamlit.io/app.py deleted file mode 100644 index 74a6b0599..000000000 --- a/embedchain/embedchain/deployment/streamlit.io/app.py +++ /dev/null @@ -1,59 +0,0 @@ -import streamlit as st - -from embedchain import App - - -@st.cache_resource -def embedchain_bot(): - return App() - - -st.title("💬 Chatbot") -st.caption("🚀 An Embedchain app powered by OpenAI!") -if "messages" not in st.session_state: - st.session_state.messages = [ - { - "role": "assistant", - "content": """ - Hi! I'm a chatbot. I can answer questions and learn new things!\n - Ask me anything and if you want me to learn something do `/add `.\n - I can learn mostly everything. :) - """, - } - ] - -for message in st.session_state.messages: - with st.chat_message(message["role"]): - st.markdown(message["content"]) - -if prompt := st.chat_input("Ask me anything!"): - app = embedchain_bot() - - if prompt.startswith("/add"): - with st.chat_message("user"): - st.markdown(prompt) - st.session_state.messages.append({"role": "user", "content": prompt}) - prompt = prompt.replace("/add", "").strip() - with st.chat_message("assistant"): - message_placeholder = st.empty() - message_placeholder.markdown("Adding to knowledge base...") - app.add(prompt) - message_placeholder.markdown(f"Added {prompt} to knowledge base!") - st.session_state.messages.append({"role": "assistant", "content": f"Added {prompt} to knowledge base!"}) - st.stop() - - with st.chat_message("user"): - st.markdown(prompt) - st.session_state.messages.append({"role": "user", "content": prompt}) - - with st.chat_message("assistant"): - msg_placeholder = st.empty() - msg_placeholder.markdown("Thinking...") - full_response = "" - - for response in app.chat(prompt): - msg_placeholder.empty() - full_response += response - - msg_placeholder.markdown(full_response) - st.session_state.messages.append({"role": "assistant", "content": full_response}) diff --git a/embedchain/embedchain/deployment/streamlit.io/requirements.txt b/embedchain/embedchain/deployment/streamlit.io/requirements.txt deleted file mode 100644 index b864076ae..000000000 --- a/embedchain/embedchain/deployment/streamlit.io/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -streamlit==1.29.0 -embedchain diff --git a/embedchain/embedchain/embedchain.py b/embedchain/embedchain/embedchain.py deleted file mode 100644 index 4a1a4dc09..000000000 --- a/embedchain/embedchain/embedchain.py +++ /dev/null @@ -1,789 +0,0 @@ -import hashlib -import json -import logging -from typing import Any, Optional, Union - -from dotenv import load_dotenv -from langchain.docstore.document import Document - -from embedchain.cache import ( - adapt, - get_gptcache_session, - gptcache_data_convert, - gptcache_update_cache_callback, -) -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config import AddConfig, BaseLlmConfig, ChunkerConfig -from embedchain.config.base_app_config import BaseAppConfig -from embedchain.core.db.models import ChatHistory, DataSource -from embedchain.data_formatter import DataFormatter -from embedchain.embedder.base import BaseEmbedder -from embedchain.helpers.json_serializable import JSONSerializable -from embedchain.llm.base import BaseLlm -from embedchain.loaders.base_loader import BaseLoader -from embedchain.models.data_type import ( - DataType, - DirectDataType, - IndirectDataType, - SpecialDataType, -) -from embedchain.utils.misc import detect_datatype, is_valid_json_string -from embedchain.vectordb.base import BaseVectorDB - -load_dotenv() - -logger = logging.getLogger(__name__) - - -class EmbedChain(JSONSerializable): - def __init__( - self, - config: BaseAppConfig, - llm: BaseLlm, - db: BaseVectorDB = None, - embedder: BaseEmbedder = None, - system_prompt: Optional[str] = None, - ): - """ - Initializes the EmbedChain instance, sets up a vector DB client and - creates a collection. - - :param config: Configuration just for the app, not the db or llm or embedder. - :type config: BaseAppConfig - :param llm: Instance of the LLM you want to use. - :type llm: BaseLlm - :param db: Instance of the Database to use, defaults to None - :type db: BaseVectorDB, optional - :param embedder: instance of the embedder to use, defaults to None - :type embedder: BaseEmbedder, optional - :param system_prompt: System prompt to use in the llm query, defaults to None - :type system_prompt: Optional[str], optional - :raises ValueError: No database or embedder provided. - """ - self.config = config - self.cache_config = None - self.memory_config = None - self.mem0_memory = None - # Llm - self.llm = llm - # Database has support for config assignment for backwards compatibility - if db is None and (not hasattr(self.config, "db") or self.config.db is None): - raise ValueError("App requires Database.") - self.db = db or self.config.db - # Embedder - if embedder is None: - raise ValueError("App requires Embedder.") - self.embedder = embedder - - # Initialize database - self.db._set_embedder(self.embedder) - self.db._initialize() - # Set collection name from app config for backwards compatibility. - if config.collection_name: - self.db.set_collection_name(config.collection_name) - - # Add variables that are "shortcuts" - if system_prompt: - self.llm.config.system_prompt = system_prompt - - # Fetch the history from the database if exists - self.llm.update_history(app_id=self.config.id) - - # Attributes that aren't subclass related. - self.user_asks = [] - - self.chunker: Optional[ChunkerConfig] = None - - @property - def collect_metrics(self): - return self.config.collect_metrics - - @collect_metrics.setter - def collect_metrics(self, value): - if not isinstance(value, bool): - raise ValueError(f"Boolean value expected but got {type(value)}.") - self.config.collect_metrics = value - - @property - def online(self): - return self.llm.config.online - - @online.setter - def online(self, value): - if not isinstance(value, bool): - raise ValueError(f"Boolean value expected but got {type(value)}.") - self.llm.config.online = value - - def add( - self, - source: Any, - data_type: Optional[DataType] = None, - metadata: Optional[dict[str, Any]] = None, - config: Optional[AddConfig] = None, - dry_run=False, - loader: Optional[BaseLoader] = None, - chunker: Optional[BaseChunker] = None, - **kwargs: Optional[dict[str, Any]], - ): - """ - Adds the data from the given URL to the vector db. - Loads the data, chunks it, create embedding for each chunk - and then stores the embedding to vector database. - - :param source: The data to embed, can be a URL, local file or raw content, depending on the data type. - :type source: Any - :param data_type: Automatically detected, but can be forced with this argument. The type of the data to add, - defaults to None - :type data_type: Optional[DataType], optional - :param metadata: Metadata associated with the data source., defaults to None - :type metadata: Optional[dict[str, Any]], optional - :param config: The `AddConfig` instance to use as configuration options., defaults to None - :type config: Optional[AddConfig], optional - :raises ValueError: Invalid data type - :param dry_run: Optional. A dry run displays the chunks to ensure that the loader and chunker work as intended. - defaults to False - :type dry_run: bool - :param loader: The loader to use to load the data, defaults to None - :type loader: BaseLoader, optional - :param chunker: The chunker to use to chunk the data, defaults to None - :type chunker: BaseChunker, optional - :param kwargs: To read more params for the query function - :type kwargs: dict[str, Any] - :return: source_hash, a md5-hash of the source, in hexadecimal representation. - :rtype: str - """ - if config is not None: - pass - elif self.chunker is not None: - config = AddConfig(chunker=self.chunker) - else: - config = AddConfig() - - try: - DataType(source) - logger.warning( - f"""Starting from version v0.0.40, Embedchain can automatically detect the data type. So, in the `add` method, the argument order has changed. You no longer need to specify '{source}' for the `source` argument. So the code snippet will be `.add("{data_type}", "{source}")`""" # noqa #E501 - ) - logger.warning( - "Embedchain is swapping the arguments for you. This functionality might be deprecated in the future, so please adjust your code." # noqa #E501 - ) - source, data_type = data_type, source - except ValueError: - pass - - if data_type: - try: - data_type = DataType(data_type) - except ValueError: - logger.info( - f"Invalid data_type: '{data_type}', using `custom` instead.\n Check docs to pass the valid data type: `https://docs.embedchain.ai/data-sources/overview`" # noqa: E501 - ) - data_type = DataType.CUSTOM - - if not data_type: - data_type = detect_datatype(source) - - # `source_hash` is the md5 hash of the source argument - source_hash = hashlib.md5(str(source).encode("utf-8")).hexdigest() - - self.user_asks.append([source, data_type.value, metadata]) - - data_formatter = DataFormatter(data_type, config, loader, chunker) - documents, metadatas, _ids, new_chunks = self._load_and_embed( - data_formatter.loader, data_formatter.chunker, source, metadata, source_hash, config, dry_run, **kwargs - ) - if data_type in {DataType.DOCS_SITE}: - self.is_docs_site_instance = True - - # Convert the source to a string if it is not already - if not isinstance(source, str): - source = str(source) - - # Insert the data into the 'ec_data_sources' table - self.db_session.add( - DataSource( - hash=source_hash, - app_id=self.config.id, - type=data_type.value, - value=source, - metadata=json.dumps(metadata), - ) - ) - try: - self.db_session.commit() - except Exception as e: - logger.error(f"Error adding data source: {e}") - self.db_session.rollback() - - if dry_run: - data_chunks_info = {"chunks": documents, "metadata": metadatas, "count": len(documents), "type": data_type} - logger.debug(f"Dry run info : {data_chunks_info}") - return data_chunks_info - - # Send anonymous telemetry - if self.config.collect_metrics: - # it's quicker to check the variable twice than to count words when they won't be submitted. - word_count = data_formatter.chunker.get_word_count(documents) - - # Send anonymous telemetry - event_properties = { - **self._telemetry_props, - "data_type": data_type.value, - "word_count": word_count, - "chunks_count": new_chunks, - } - self.telemetry.capture(event_name="add", properties=event_properties) - - return source_hash - - def _get_existing_doc_id(self, chunker: BaseChunker, src: Any): - """ - Get id of existing document for a given source, based on the data type - """ - # Find existing embeddings for the source - # Depending on the data type, existing embeddings are checked for. - if chunker.data_type.value in [item.value for item in DirectDataType]: - # DirectDataTypes can't be updated. - # Think of a text: - # Either it's the same, then it won't change, so it's not an update. - # Or it's different, then it will be added as a new text. - return None - elif chunker.data_type.value in [item.value for item in IndirectDataType]: - # These types have an indirect source reference - # As long as the reference is the same, they can be updated. - where = {"url": src} - if chunker.data_type == DataType.JSON and is_valid_json_string(src): - url = hashlib.sha256((src).encode("utf-8")).hexdigest() - where = {"url": url} - - if self.config.id is not None: - where.update({"app_id": self.config.id}) - - existing_embeddings = self.db.get( - where=where, - limit=1, - ) - if len(existing_embeddings.get("metadatas", [])) > 0: - return existing_embeddings["metadatas"][0]["doc_id"] - else: - return None - elif chunker.data_type.value in [item.value for item in SpecialDataType]: - # These types don't contain indirect references. - # Through custom logic, they can be attributed to a source and be updated. - if chunker.data_type == DataType.QNA_PAIR: - # QNA_PAIRs update the answer if the question already exists. - where = {"question": src[0]} - if self.config.id is not None: - where.update({"app_id": self.config.id}) - - existing_embeddings = self.db.get( - where=where, - limit=1, - ) - if len(existing_embeddings.get("metadatas", [])) > 0: - return existing_embeddings["metadatas"][0]["doc_id"] - else: - return None - else: - raise NotImplementedError( - f"SpecialDataType {chunker.data_type} must have a custom logic to check for existing data" - ) - else: - raise TypeError( - f"{chunker.data_type} is type {type(chunker.data_type)}. " - "When it should be DirectDataType, IndirectDataType or SpecialDataType." - ) - - def _load_and_embed( - self, - loader: BaseLoader, - chunker: BaseChunker, - src: Any, - metadata: Optional[dict[str, Any]] = None, - source_hash: Optional[str] = None, - add_config: Optional[AddConfig] = None, - dry_run=False, - **kwargs: Optional[dict[str, Any]], - ): - """ - Loads the data from the given URL, chunks it, and adds it to database. - - :param loader: The loader to use to load the data. - :type loader: BaseLoader - :param chunker: The chunker to use to chunk the data. - :type chunker: BaseChunker - :param src: The data to be handled by the loader. Can be a URL for - remote sources or local content for local loaders. - :type src: Any - :param metadata: Metadata associated with the data source. - :type metadata: dict[str, Any], optional - :param source_hash: Hexadecimal hash of the source. - :type source_hash: str, optional - :param add_config: The `AddConfig` instance to use as configuration options. - :type add_config: AddConfig, optional - :param dry_run: A dry run returns chunks and doesn't update DB. - :type dry_run: bool, defaults to False - :return: (list) documents (embedded text), (list) metadata, (list) ids, (int) number of chunks - """ - existing_doc_id = self._get_existing_doc_id(chunker=chunker, src=src) - app_id = self.config.id if self.config is not None else None - - # Create chunks - embeddings_data = chunker.create_chunks(loader, src, app_id=app_id, config=add_config.chunker, **kwargs) - # spread chunking results - documents = embeddings_data["documents"] - metadatas = embeddings_data["metadatas"] - ids = embeddings_data["ids"] - new_doc_id = embeddings_data["doc_id"] - - if existing_doc_id and existing_doc_id == new_doc_id: - logger.info("Doc content has not changed. Skipping creating chunks and embeddings") - return [], [], [], 0 - - # this means that doc content has changed. - if existing_doc_id and existing_doc_id != new_doc_id: - logger.info("Doc content has changed. Recomputing chunks and embeddings intelligently.") - self.db.delete({"doc_id": existing_doc_id}) - - # get existing ids, and discard doc if any common id exist. - where = {"url": src} - if chunker.data_type == DataType.JSON and is_valid_json_string(src): - url = hashlib.sha256((src).encode("utf-8")).hexdigest() - where = {"url": url} - - # if data type is qna_pair, we check for question - if chunker.data_type == DataType.QNA_PAIR: - where = {"question": src[0]} - - if self.config.id is not None: - where["app_id"] = self.config.id - - db_result = self.db.get(ids=ids, where=where) # optional filter - existing_ids = set(db_result["ids"]) - if len(existing_ids): - data_dict = {id: (doc, meta) for id, doc, meta in zip(ids, documents, metadatas)} - data_dict = {id: value for id, value in data_dict.items() if id not in existing_ids} - - if not data_dict: - src_copy = src - if len(src_copy) > 50: - src_copy = src[:50] + "..." - logger.info(f"All data from {src_copy} already exists in the database.") - # Make sure to return a matching return type - return [], [], [], 0 - - ids = list(data_dict.keys()) - documents, metadatas = zip(*data_dict.values()) - - # Loop though all metadatas and add extras. - new_metadatas = [] - for m in metadatas: - # Add app id in metadatas so that they can be queried on later - if self.config.id: - m["app_id"] = self.config.id - - # Add hashed source - m["hash"] = source_hash - - # Note: Metadata is the function argument - if metadata: - # Spread whatever is in metadata into the new object. - m.update(metadata) - - new_metadatas.append(m) - metadatas = new_metadatas - - if dry_run: - return list(documents), metadatas, ids, 0 - - # Count before, to calculate a delta in the end. - chunks_before_addition = self.db.count() - - # Filter out empty documents and ensure they meet the API requirements - valid_documents = [doc for doc in documents if doc and isinstance(doc, str)] - - documents = valid_documents - - # Chunk documents into batches of 2048 and handle each batch - # helps wigth large loads of embeddings that hit OpenAI limits - document_batches = [documents[i : i + 2048] for i in range(0, len(documents), 2048)] - metadata_batches = [metadatas[i : i + 2048] for i in range(0, len(metadatas), 2048)] - id_batches = [ids[i : i + 2048] for i in range(0, len(ids), 2048)] - for batch_docs, batch_meta, batch_ids in zip(document_batches, metadata_batches, id_batches): - try: - # Add only valid batches - if batch_docs: - self.db.add(documents=batch_docs, metadatas=batch_meta, ids=batch_ids, **kwargs) - except Exception as e: - logger.info(f"Failed to add batch due to a bad request: {e}") - # Handle the error, e.g., by logging, retrying, or skipping - pass - - count_new_chunks = self.db.count() - chunks_before_addition - logger.info(f"Successfully saved {str(src)[:100]} ({chunker.data_type}). New chunks count: {count_new_chunks}") - - return list(documents), metadatas, ids, count_new_chunks - - @staticmethod - def _format_result(results): - return [ - (Document(page_content=result[0], metadata=result[1] or {}), result[2]) - for result in zip( - results["documents"][0], - results["metadatas"][0], - results["distances"][0], - ) - ] - - def _retrieve_from_database( - self, - input_query: str, - config: Optional[BaseLlmConfig] = None, - where=None, - citations: bool = False, - **kwargs: Optional[dict[str, Any]], - ) -> Union[list[tuple[str, str, str]], list[str]]: - """ - Queries the vector database based on the given input query. - Gets relevant doc based on the query - - :param input_query: The query to use. - :type input_query: str - :param config: The query configuration, defaults to None - :type config: Optional[BaseLlmConfig], optional - :param where: A dictionary of key-value pairs to filter the database results, defaults to None - :type where: _type_, optional - :param citations: A boolean to indicate if db should fetch citation source - :type citations: bool - :return: List of contents of the document that matched your query - :rtype: list[str] - """ - query_config = config or self.llm.config - if where is not None: - where = where - else: - where = {} - if query_config is not None and query_config.where is not None: - where = query_config.where - - if self.config.id is not None: - where.update({"app_id": self.config.id}) - - contexts = self.db.query( - input_query=input_query, - n_results=query_config.number_documents, - where=where, - citations=citations, - **kwargs, - ) - - return contexts - - def query( - self, - input_query: str, - config: BaseLlmConfig = None, - dry_run=False, - where: Optional[dict] = None, - citations: bool = False, - **kwargs: dict[str, Any], - ) -> Union[tuple[str, list[tuple[str, dict]]], str, dict[str, Any]]: - """ - Queries the vector database based on the given input query. - Gets relevant doc based on the query and then passes it to an - LLM as context to get the answer. - - :param input_query: The query to use. - :type input_query: str - :param config: The `BaseLlmConfig` instance to use as configuration options. This is used for one method call. - To persistently use a config, declare it during app init., defaults to None - :type config: BaseLlmConfig, optional - :param dry_run: A dry run does everything except send the resulting prompt to - the LLM. The purpose is to test the prompt, not the response., defaults to False - :type dry_run: bool, optional - :param where: A dictionary of key-value pairs to filter the database results., defaults to None - :type where: dict[str, str], optional - :param citations: A boolean to indicate if db should fetch citation source - :type citations: bool - :param kwargs: To read more params for the query function. Ex. we use citations boolean - param to return context along with the answer - :type kwargs: dict[str, Any] - :return: The answer to the query, with citations if the citation flag is True - or the dry run result - :rtype: str, if citations is False and token_usage is False, otherwise if citations is true then - tuple[str, list[tuple[str,str,str]]] and if token_usage is true then - tuple[str, list[tuple[str,str,str]], dict[str, Any]] - """ - contexts = self._retrieve_from_database( - input_query=input_query, config=config, where=where, citations=citations, **kwargs - ) - if citations and len(contexts) > 0 and isinstance(contexts[0], tuple): - contexts_data_for_llm_query = list(map(lambda x: x[0], contexts)) - else: - contexts_data_for_llm_query = contexts - - if self.cache_config is not None: - logger.info("Cache enabled. Checking cache...") - answer = adapt( - llm_handler=self.llm.query, - cache_data_convert=gptcache_data_convert, - update_cache_callback=gptcache_update_cache_callback, - session=get_gptcache_session(session_id=self.config.id), - input_query=input_query, - contexts=contexts_data_for_llm_query, - config=config, - dry_run=dry_run, - ) - else: - if self.llm.config.token_usage: - answer, token_info = self.llm.query( - input_query=input_query, contexts=contexts_data_for_llm_query, config=config, dry_run=dry_run - ) - else: - answer = self.llm.query( - input_query=input_query, contexts=contexts_data_for_llm_query, config=config, dry_run=dry_run - ) - - # Send anonymous telemetry - if self.config.collect_metrics: - self.telemetry.capture(event_name="query", properties=self._telemetry_props) - - if citations: - if self.llm.config.token_usage: - return {"answer": answer, "contexts": contexts, "usage": token_info} - return answer, contexts - if self.llm.config.token_usage: - return {"answer": answer, "usage": token_info} - - logger.warning( - "Starting from v0.1.125 the return type of query method will be changed to tuple containing `answer`." - ) - return answer - - def chat( - self, - input_query: str, - config: Optional[BaseLlmConfig] = None, - dry_run=False, - session_id: str = "default", - where: Optional[dict[str, str]] = None, - citations: bool = False, - **kwargs: dict[str, Any], - ) -> Union[tuple[str, list[tuple[str, dict]]], str, dict[str, Any]]: - """ - Queries the vector database on the given input query. - Gets relevant doc based on the query and then passes it to an - LLM as context to get the answer. - - Maintains the whole conversation in memory. - - :param input_query: The query to use. - :type input_query: str - :param config: The `BaseLlmConfig` instance to use as configuration options. This is used for one method call. - To persistently use a config, declare it during app init., defaults to None - :type config: BaseLlmConfig, optional - :param dry_run: A dry run does everything except send the resulting prompt to - the LLM. The purpose is to test the prompt, not the response., defaults to False - :type dry_run: bool, optional - :param session_id: The session id to use for chat history, defaults to 'default'. - :type session_id: str, optional - :param where: A dictionary of key-value pairs to filter the database results., defaults to None - :type where: dict[str, str], optional - :param citations: A boolean to indicate if db should fetch citation source - :type citations: bool - :param kwargs: To read more params for the query function. Ex. we use citations boolean - param to return context along with the answer - :type kwargs: dict[str, Any] - :return: The answer to the query, with citations if the citation flag is True - or the dry run result - :rtype: str, if citations is False and token_usage is False, otherwise if citations is true then - tuple[str, list[tuple[str,str,str]]] and if token_usage is true then - tuple[str, list[tuple[str,str,str]], dict[str, Any]] - """ - contexts = self._retrieve_from_database( - input_query=input_query, config=config, where=where, citations=citations, **kwargs - ) - if citations and len(contexts) > 0 and isinstance(contexts[0], tuple): - contexts_data_for_llm_query = list(map(lambda x: x[0], contexts)) - else: - contexts_data_for_llm_query = contexts - - memories = None - if self.mem0_memory: - memories = self.mem0_memory.search( - query=input_query, agent_id=self.config.id, user_id=session_id, limit=self.memory_config.top_k - ) - - # Update the history beforehand so that we can handle multiple chat sessions in the same python session - self.llm.update_history(app_id=self.config.id, session_id=session_id) - - if self.cache_config is not None: - logger.debug("Cache enabled. Checking cache...") - cache_id = f"{session_id}--{self.config.id}" - answer = adapt( - llm_handler=self.llm.chat, - cache_data_convert=gptcache_data_convert, - update_cache_callback=gptcache_update_cache_callback, - session=get_gptcache_session(session_id=cache_id), - input_query=input_query, - contexts=contexts_data_for_llm_query, - config=config, - dry_run=dry_run, - ) - else: - logger.debug("Cache disabled. Running chat without cache.") - if self.llm.config.token_usage: - answer, token_info = self.llm.query( - input_query=input_query, - contexts=contexts_data_for_llm_query, - config=config, - dry_run=dry_run, - memories=memories, - ) - else: - answer = self.llm.query( - input_query=input_query, - contexts=contexts_data_for_llm_query, - config=config, - dry_run=dry_run, - memories=memories, - ) - - # Add to Mem0 memory if enabled - # Adding answer here because it would be much useful than input question itself - if self.mem0_memory: - self.mem0_memory.add(data=answer, agent_id=self.config.id, user_id=session_id) - - # add conversation in memory - self.llm.add_history(self.config.id, input_query, answer, session_id=session_id) - - # Send anonymous telemetry - if self.config.collect_metrics: - self.telemetry.capture(event_name="chat", properties=self._telemetry_props) - - if citations: - if self.llm.config.token_usage: - return {"answer": answer, "contexts": contexts, "usage": token_info} - return answer, contexts - if self.llm.config.token_usage: - return {"answer": answer, "usage": token_info} - - logger.warning( - "Starting from v0.1.125 the return type of query method will be changed to tuple containing `answer`." - ) - return answer - - def search(self, query, num_documents=3, where=None, raw_filter=None, namespace=None): - """ - Search for similar documents related to the query in the vector database. - - Args: - query (str): The query to use. - num_documents (int, optional): Number of similar documents to fetch. Defaults to 3. - where (dict[str, any], optional): Filter criteria for the search. - raw_filter (dict[str, any], optional): Advanced raw filter criteria for the search. - namespace (str, optional): The namespace to search in. Defaults to None. - - Raises: - ValueError: If both `raw_filter` and `where` are used simultaneously. - - Returns: - list[dict]: A list of dictionaries, each containing the 'context' and 'metadata' of a document. - """ - # Send anonymous telemetry - if self.config.collect_metrics: - self.telemetry.capture(event_name="search", properties=self._telemetry_props) - - if raw_filter and where: - raise ValueError("You can't use both `raw_filter` and `where` together.") - - filter_type = "raw_filter" if raw_filter else "where" - filter_criteria = raw_filter if raw_filter else where - - params = { - "input_query": query, - "n_results": num_documents, - "citations": True, - "app_id": self.config.id, - "namespace": namespace, - filter_type: filter_criteria, - } - - return [{"context": c[0], "metadata": c[1]} for c in self.db.query(**params)] - - def set_collection_name(self, name: str): - """ - Set the name of the collection. A collection is an isolated space for vectors. - - Using `app.db.set_collection_name` method is preferred to this. - - :param name: Name of the collection. - :type name: str - """ - self.db.set_collection_name(name) - # Create the collection if it does not exist - self.db._get_or_create_collection(name) - # TODO: Check whether it is necessary to assign to the `self.collection` attribute, - # since the main purpose is the creation. - - def reset(self): - """ - Resets the database. Deletes all embeddings irreversibly. - `App` does not have to be reinitialized after using this method. - """ - try: - self.db_session.query(DataSource).filter_by(app_id=self.config.id).delete() - self.db_session.query(ChatHistory).filter_by(app_id=self.config.id).delete() - self.db_session.commit() - except Exception as e: - logger.error(f"Error deleting data sources: {e}") - self.db_session.rollback() - return None - self.db.reset() - self.delete_all_chat_history(app_id=self.config.id) - # Send anonymous telemetry - if self.config.collect_metrics: - self.telemetry.capture(event_name="reset", properties=self._telemetry_props) - - def get_history( - self, - num_rounds: int = 10, - display_format: bool = True, - session_id: Optional[str] = "default", - fetch_all: bool = False, - ): - history = self.llm.memory.get( - app_id=self.config.id, - session_id=session_id, - num_rounds=num_rounds, - display_format=display_format, - fetch_all=fetch_all, - ) - return history - - def delete_session_chat_history(self, session_id: str = "default"): - self.llm.memory.delete(app_id=self.config.id, session_id=session_id) - self.llm.update_history(app_id=self.config.id) - - def delete_all_chat_history(self, app_id: str): - self.llm.memory.delete(app_id=app_id) - self.llm.update_history(app_id=app_id) - - def delete(self, source_id: str): - """ - Deletes the data from the database. - :param source_hash: The hash of the source. - :type source_hash: str - """ - try: - self.db_session.query(DataSource).filter_by(hash=source_id, app_id=self.config.id).delete() - self.db_session.commit() - except Exception as e: - logger.error(f"Error deleting data sources: {e}") - self.db_session.rollback() - return None - self.db.delete(where={"hash": source_id}) - logger.info(f"Successfully deleted {source_id}") - # Send anonymous telemetry - if self.config.collect_metrics: - self.telemetry.capture(event_name="delete", properties=self._telemetry_props) diff --git a/embedchain/embedchain/embedder/__init__.py b/embedchain/embedchain/embedder/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/embedder/aws_bedrock.py b/embedchain/embedchain/embedder/aws_bedrock.py deleted file mode 100644 index 235fc3dab..000000000 --- a/embedchain/embedchain/embedder/aws_bedrock.py +++ /dev/null @@ -1,31 +0,0 @@ -from typing import Optional - -try: - from langchain_aws import BedrockEmbeddings -except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for AWSBedrock are not installed." "Please install with `pip install langchain_aws`" - ) from None - -from embedchain.config.embedder.aws_bedrock import AWSBedrockEmbedderConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.models import VectorDimensions - - -class AWSBedrockEmbedder(BaseEmbedder): - def __init__(self, config: Optional[AWSBedrockEmbedderConfig] = None): - super().__init__(config) - - if self.config.model is None or self.config.model == "amazon.titan-embed-text-v2:0": - self.config.model = "amazon.titan-embed-text-v2:0" # Default model if not specified - vector_dimension = self.config.vector_dimension or VectorDimensions.AMAZON_TITAN_V2.value - elif self.config.model == "amazon.titan-embed-text-v1": - vector_dimension = VectorDimensions.AMAZON_TITAN_V1.value - else: - vector_dimension = self.config.vector_dimension - - embeddings = BedrockEmbeddings(model_id=self.config.model, model_kwargs=self.config.model_kwargs) - embedding_fn = BaseEmbedder._langchain_default_concept(embeddings) - - self.set_embedding_fn(embedding_fn=embedding_fn) - self.set_vector_dimension(vector_dimension=vector_dimension) diff --git a/embedchain/embedchain/embedder/azure_openai.py b/embedchain/embedchain/embedder/azure_openai.py deleted file mode 100644 index 71802ad87..000000000 --- a/embedchain/embedchain/embedder/azure_openai.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Optional - -from langchain_openai import AzureOpenAIEmbeddings - -from embedchain.config import BaseEmbedderConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.models import VectorDimensions - - -class AzureOpenAIEmbedder(BaseEmbedder): - def __init__(self, config: Optional[BaseEmbedderConfig] = None): - super().__init__(config=config) - - if self.config.model is None: - self.config.model = "text-embedding-ada-002" - - embeddings = AzureOpenAIEmbeddings( - deployment=self.config.deployment_name, - http_client=self.config.http_client, - http_async_client=self.config.http_async_client, - ) - embedding_fn = BaseEmbedder._langchain_default_concept(embeddings) - - self.set_embedding_fn(embedding_fn=embedding_fn) - vector_dimension = self.config.vector_dimension or VectorDimensions.OPENAI.value - self.set_vector_dimension(vector_dimension=vector_dimension) diff --git a/embedchain/embedchain/embedder/base.py b/embedchain/embedchain/embedder/base.py deleted file mode 100644 index 7f65477bf..000000000 --- a/embedchain/embedchain/embedder/base.py +++ /dev/null @@ -1,90 +0,0 @@ -from collections.abc import Callable -from typing import Any, Optional - -from embedchain.config.embedder.base import BaseEmbedderConfig - -try: - from chromadb.api.types import Embeddable, EmbeddingFunction, Embeddings -except RuntimeError: - from embedchain.utils.misc import use_pysqlite3 - - use_pysqlite3() - from chromadb.api.types import Embeddable, EmbeddingFunction, Embeddings - - -class EmbeddingFunc(EmbeddingFunction): - def __init__(self, embedding_fn: Callable[[list[str]], list[str]]): - self.embedding_fn = embedding_fn - - def __call__(self, input: Embeddable) -> Embeddings: - return self.embedding_fn(input) - - -class BaseEmbedder: - """ - Class that manages everything regarding embeddings. Including embedding function, loaders and chunkers. - - Embedding functions and vector dimensions are set based on the child class you choose. - To manually overwrite you can use this classes `set_...` methods. - """ - - def __init__(self, config: Optional[BaseEmbedderConfig] = None): - """ - Initialize the embedder class. - - :param config: embedder configuration option class, defaults to None - :type config: Optional[BaseEmbedderConfig], optional - """ - if config is None: - self.config = BaseEmbedderConfig() - else: - self.config = config - self.vector_dimension: int - - def set_embedding_fn(self, embedding_fn: Callable[[list[str]], list[str]]): - """ - Set or overwrite the embedding function to be used by the database to store and retrieve documents. - - :param embedding_fn: Function to be used to generate embeddings. - :type embedding_fn: Callable[[list[str]], list[str]] - :raises ValueError: Embedding function is not callable. - """ - if not hasattr(embedding_fn, "__call__"): - raise ValueError("Embedding function is not a function") - self.embedding_fn = embedding_fn - - def set_vector_dimension(self, vector_dimension: int): - """ - Set or overwrite the vector dimension size - - :param vector_dimension: vector dimension size - :type vector_dimension: int - """ - if not isinstance(vector_dimension, int): - raise TypeError("vector dimension must be int") - self.vector_dimension = vector_dimension - - @staticmethod - def _langchain_default_concept(embeddings: Any): - """ - Langchains default function layout for embeddings. - - :param embeddings: Langchain embeddings - :type embeddings: Any - :return: embedding function - :rtype: Callable - """ - - return EmbeddingFunc(embeddings.embed_documents) - - def to_embeddings(self, data: str, **_): - """ - Convert data to embeddings - - :param data: data to convert to embeddings - :type data: str - :return: embeddings - :rtype: list[float] - """ - embeddings = self.embedding_fn([data]) - return embeddings[0] diff --git a/embedchain/embedchain/embedder/clarifai.py b/embedchain/embedchain/embedder/clarifai.py deleted file mode 100644 index 8f0bb2fe4..000000000 --- a/embedchain/embedchain/embedder/clarifai.py +++ /dev/null @@ -1,52 +0,0 @@ -import os -from typing import Optional, Union - -from chromadb import EmbeddingFunction, Embeddings - -from embedchain.config import BaseEmbedderConfig -from embedchain.embedder.base import BaseEmbedder - - -class ClarifaiEmbeddingFunction(EmbeddingFunction): - def __init__(self, config: BaseEmbedderConfig) -> None: - super().__init__() - try: - from clarifai.client.input import Inputs - from clarifai.client.model import Model - except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for ClarifaiEmbeddingFunction are not installed." - 'Please install with `pip install --upgrade "embedchain[clarifai]"`' - ) from None - self.config = config - self.api_key = config.api_key or os.getenv("CLARIFAI_PAT") - self.model = config.model - self.model_obj = Model(url=self.model, pat=self.api_key) - self.input_obj = Inputs(pat=self.api_key) - - def __call__(self, input: Union[str, list[str]]) -> Embeddings: - if isinstance(input, str): - input = [input] - - batch_size = 32 - embeddings = [] - try: - for i in range(0, len(input), batch_size): - batch = input[i : i + batch_size] - input_batch = [ - self.input_obj.get_text_input(input_id=str(id), raw_text=inp) for id, inp in enumerate(batch) - ] - response = self.model_obj.predict(input_batch) - embeddings.extend([list(output.data.embeddings[0].vector) for output in response.outputs]) - except Exception as e: - print(f"Predict failed, exception: {e}") - - return embeddings - - -class ClarifaiEmbedder(BaseEmbedder): - def __init__(self, config: Optional[BaseEmbedderConfig] = None): - super().__init__(config) - - embedding_func = ClarifaiEmbeddingFunction(config=self.config) - self.set_embedding_fn(embedding_fn=embedding_func) diff --git a/embedchain/embedchain/embedder/cohere.py b/embedchain/embedchain/embedder/cohere.py deleted file mode 100644 index 489ba97f3..000000000 --- a/embedchain/embedchain/embedder/cohere.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Optional - -from langchain_cohere.embeddings import CohereEmbeddings - -from embedchain.config import BaseEmbedderConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.models import VectorDimensions - - -class CohereEmbedder(BaseEmbedder): - def __init__(self, config: Optional[BaseEmbedderConfig] = None): - super().__init__(config=config) - - embeddings = CohereEmbeddings(model=self.config.model) - embedding_fn = BaseEmbedder._langchain_default_concept(embeddings) - self.set_embedding_fn(embedding_fn=embedding_fn) - - vector_dimension = self.config.vector_dimension or VectorDimensions.COHERE.value - self.set_vector_dimension(vector_dimension=vector_dimension) diff --git a/embedchain/embedchain/embedder/google.py b/embedchain/embedchain/embedder/google.py deleted file mode 100644 index c0be83500..000000000 --- a/embedchain/embedchain/embedder/google.py +++ /dev/null @@ -1,38 +0,0 @@ -from typing import Optional, Union - -import google.generativeai as genai -from chromadb import EmbeddingFunction, Embeddings - -from embedchain.config.embedder.google import GoogleAIEmbedderConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.models import VectorDimensions - - -class GoogleAIEmbeddingFunction(EmbeddingFunction): - def __init__(self, config: Optional[GoogleAIEmbedderConfig] = None) -> None: - super().__init__() - self.config = config or GoogleAIEmbedderConfig() - - def __call__(self, input: Union[list[str], str]) -> Embeddings: - model = self.config.model - title = self.config.title - task_type = self.config.task_type - if isinstance(input, str): - input_ = [input] - else: - input_ = input - data = genai.embed_content(model=model, content=input_, task_type=task_type, title=title) - embeddings = data["embedding"] - if isinstance(input_, str): - embeddings = [embeddings] - return embeddings - - -class GoogleAIEmbedder(BaseEmbedder): - def __init__(self, config: Optional[GoogleAIEmbedderConfig] = None): - super().__init__(config) - embedding_fn = GoogleAIEmbeddingFunction(config=config) - self.set_embedding_fn(embedding_fn=embedding_fn) - - vector_dimension = self.config.vector_dimension or VectorDimensions.GOOGLE_AI.value - self.set_vector_dimension(vector_dimension=vector_dimension) diff --git a/embedchain/embedchain/embedder/gpt4all.py b/embedchain/embedchain/embedder/gpt4all.py deleted file mode 100644 index 83123f499..000000000 --- a/embedchain/embedchain/embedder/gpt4all.py +++ /dev/null @@ -1,23 +0,0 @@ -from typing import Optional - -from embedchain.config import BaseEmbedderConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.models import VectorDimensions - - -class GPT4AllEmbedder(BaseEmbedder): - def __init__(self, config: Optional[BaseEmbedderConfig] = None): - super().__init__(config=config) - - from langchain_community.embeddings import ( - GPT4AllEmbeddings as LangchainGPT4AllEmbeddings, - ) - - model_name = self.config.model or "all-MiniLM-L6-v2-f16.gguf" - gpt4all_kwargs = {'allow_download': 'True'} - embeddings = LangchainGPT4AllEmbeddings(model_name=model_name, gpt4all_kwargs=gpt4all_kwargs) - embedding_fn = BaseEmbedder._langchain_default_concept(embeddings) - self.set_embedding_fn(embedding_fn=embedding_fn) - - vector_dimension = self.config.vector_dimension or VectorDimensions.GPT4ALL.value - self.set_vector_dimension(vector_dimension=vector_dimension) diff --git a/embedchain/embedchain/embedder/huggingface.py b/embedchain/embedchain/embedder/huggingface.py deleted file mode 100644 index 062208e77..000000000 --- a/embedchain/embedchain/embedder/huggingface.py +++ /dev/null @@ -1,40 +0,0 @@ -import os -from typing import Optional - -from langchain_community.embeddings import HuggingFaceEmbeddings - -try: - from langchain_huggingface import HuggingFaceEndpointEmbeddings -except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for HuggingFaceHub are not installed." - "Please install with `pip install langchain_huggingface`" - ) from None - -from embedchain.config import BaseEmbedderConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.models import VectorDimensions - - -class HuggingFaceEmbedder(BaseEmbedder): - def __init__(self, config: Optional[BaseEmbedderConfig] = None): - super().__init__(config=config) - - if self.config.endpoint: - if not self.config.api_key and "HUGGINGFACE_ACCESS_TOKEN" not in os.environ: - raise ValueError( - "Please set the HUGGINGFACE_ACCESS_TOKEN environment variable or pass API Key in the config." - ) - - embeddings = HuggingFaceEndpointEmbeddings( - model=self.config.endpoint, - huggingfacehub_api_token=self.config.api_key or os.getenv("HUGGINGFACE_ACCESS_TOKEN"), - ) - else: - embeddings = HuggingFaceEmbeddings(model_name=self.config.model, model_kwargs=self.config.model_kwargs) - - embedding_fn = BaseEmbedder._langchain_default_concept(embeddings) - self.set_embedding_fn(embedding_fn=embedding_fn) - - vector_dimension = self.config.vector_dimension or VectorDimensions.HUGGING_FACE.value - self.set_vector_dimension(vector_dimension=vector_dimension) diff --git a/embedchain/embedchain/embedder/mistralai.py b/embedchain/embedchain/embedder/mistralai.py deleted file mode 100644 index 29db72ae0..000000000 --- a/embedchain/embedchain/embedder/mistralai.py +++ /dev/null @@ -1,46 +0,0 @@ -import os -from typing import Optional, Union - -from chromadb import EmbeddingFunction, Embeddings - -from embedchain.config import BaseEmbedderConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.models import VectorDimensions - - -class MistralAIEmbeddingFunction(EmbeddingFunction): - def __init__(self, config: BaseEmbedderConfig) -> None: - super().__init__() - try: - from langchain_mistralai import MistralAIEmbeddings - except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for MistralAI are not installed." - 'Please install with `pip install --upgrade "embedchain[mistralai]"`' - ) from None - self.config = config - api_key = self.config.api_key or os.getenv("MISTRAL_API_KEY") - self.client = MistralAIEmbeddings(mistral_api_key=api_key) - self.client.model = self.config.model - - def __call__(self, input: Union[list[str], str]) -> Embeddings: - if isinstance(input, str): - input_ = [input] - else: - input_ = input - response = self.client.embed_documents(input_) - return response - - -class MistralAIEmbedder(BaseEmbedder): - def __init__(self, config: Optional[BaseEmbedderConfig] = None): - super().__init__(config) - - if self.config.model is None: - self.config.model = "mistral-embed" - - embedding_fn = MistralAIEmbeddingFunction(config=self.config) - self.set_embedding_fn(embedding_fn=embedding_fn) - - vector_dimension = self.config.vector_dimension or VectorDimensions.MISTRAL_AI.value - self.set_vector_dimension(vector_dimension=vector_dimension) diff --git a/embedchain/embedchain/embedder/nvidia.py b/embedchain/embedchain/embedder/nvidia.py deleted file mode 100644 index 5a499037f..000000000 --- a/embedchain/embedchain/embedder/nvidia.py +++ /dev/null @@ -1,28 +0,0 @@ -import logging -import os -from typing import Optional - -from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings - -from embedchain.config import BaseEmbedderConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.models import VectorDimensions - -logger = logging.getLogger(__name__) - - -class NvidiaEmbedder(BaseEmbedder): - def __init__(self, config: Optional[BaseEmbedderConfig] = None): - if "NVIDIA_API_KEY" not in os.environ: - raise ValueError("NVIDIA_API_KEY environment variable must be set") - - super().__init__(config=config) - - model = self.config.model or "nvolveqa_40k" - logger.info(f"Using NVIDIA embedding model: {model}") - embedder = NVIDIAEmbeddings(model=model) - embedding_fn = BaseEmbedder._langchain_default_concept(embedder) - self.set_embedding_fn(embedding_fn=embedding_fn) - - vector_dimension = self.config.vector_dimension or VectorDimensions.NVIDIA_AI.value - self.set_vector_dimension(vector_dimension=vector_dimension) diff --git a/embedchain/embedchain/embedder/ollama.py b/embedchain/embedchain/embedder/ollama.py deleted file mode 100644 index 9e4ada473..000000000 --- a/embedchain/embedchain/embedder/ollama.py +++ /dev/null @@ -1,32 +0,0 @@ -import logging -from typing import Optional - -try: - from ollama import Client -except ImportError: - raise ImportError("Ollama Embedder requires extra dependencies. Install with `pip install ollama`") from None - -from langchain_community.embeddings import OllamaEmbeddings - -from embedchain.config import OllamaEmbedderConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.models import VectorDimensions - -logger = logging.getLogger(__name__) - - -class OllamaEmbedder(BaseEmbedder): - def __init__(self, config: Optional[OllamaEmbedderConfig] = None): - super().__init__(config=config) - - client = Client(host=config.base_url) - local_models = client.list()["models"] - if not any(model.get("name") == self.config.model for model in local_models): - logger.info(f"Pulling {self.config.model} from Ollama!") - client.pull(self.config.model) - embeddings = OllamaEmbeddings(model=self.config.model, base_url=config.base_url) - embedding_fn = BaseEmbedder._langchain_default_concept(embeddings) - self.set_embedding_fn(embedding_fn=embedding_fn) - - vector_dimension = self.config.vector_dimension or VectorDimensions.OLLAMA.value - self.set_vector_dimension(vector_dimension=vector_dimension) diff --git a/embedchain/embedchain/embedder/openai.py b/embedchain/embedchain/embedder/openai.py deleted file mode 100644 index e14a1aa70..000000000 --- a/embedchain/embedchain/embedder/openai.py +++ /dev/null @@ -1,43 +0,0 @@ -import os -import warnings -from typing import Optional - -from chromadb.utils.embedding_functions import OpenAIEmbeddingFunction - -from embedchain.config import BaseEmbedderConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.models import VectorDimensions - - -class OpenAIEmbedder(BaseEmbedder): - def __init__(self, config: Optional[BaseEmbedderConfig] = None): - super().__init__(config=config) - - if self.config.model is None: - self.config.model = "text-embedding-ada-002" - - api_key = self.config.api_key or os.environ["OPENAI_API_KEY"] - api_base = ( - self.config.api_base - or os.environ.get("OPENAI_API_BASE") - or os.getenv("OPENAI_BASE_URL") - or "https://api.openai.com/v1" - ) - if os.environ.get("OPENAI_API_BASE"): - warnings.warn( - "The environment variable 'OPENAI_API_BASE' is deprecated and will be removed in the 0.1.140. " - "Please use 'OPENAI_BASE_URL' instead.", - DeprecationWarning - ) - - if api_key is None and os.getenv("OPENAI_ORGANIZATION") is None: - raise ValueError("OPENAI_API_KEY or OPENAI_ORGANIZATION environment variables not provided") # noqa:E501 - embedding_fn = OpenAIEmbeddingFunction( - api_key=api_key, - api_base=api_base, - organization_id=os.getenv("OPENAI_ORGANIZATION"), - model_name=self.config.model, - ) - self.set_embedding_fn(embedding_fn=embedding_fn) - vector_dimension = self.config.vector_dimension or VectorDimensions.OPENAI.value - self.set_vector_dimension(vector_dimension=vector_dimension) diff --git a/embedchain/embedchain/embedder/vertexai.py b/embedchain/embedchain/embedder/vertexai.py deleted file mode 100644 index 1f3331dc6..000000000 --- a/embedchain/embedchain/embedder/vertexai.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Optional - -from langchain_google_vertexai import VertexAIEmbeddings - -from embedchain.config import BaseEmbedderConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.models import VectorDimensions - - -class VertexAIEmbedder(BaseEmbedder): - def __init__(self, config: Optional[BaseEmbedderConfig] = None): - super().__init__(config=config) - - embeddings = VertexAIEmbeddings(model_name=config.model) - embedding_fn = BaseEmbedder._langchain_default_concept(embeddings) - self.set_embedding_fn(embedding_fn=embedding_fn) - - vector_dimension = self.config.vector_dimension or VectorDimensions.VERTEX_AI.value - self.set_vector_dimension(vector_dimension=vector_dimension) diff --git a/embedchain/embedchain/evaluation/__init__.py b/embedchain/embedchain/evaluation/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/evaluation/base.py b/embedchain/embedchain/evaluation/base.py deleted file mode 100644 index 4528e7689..000000000 --- a/embedchain/embedchain/evaluation/base.py +++ /dev/null @@ -1,29 +0,0 @@ -from abc import ABC, abstractmethod - -from embedchain.utils.evaluation import EvalData - - -class BaseMetric(ABC): - """Base class for a metric. - - This class provides a common interface for all metrics. - """ - - def __init__(self, name: str = "base_metric"): - """ - Initialize the BaseMetric. - """ - self.name = name - - @abstractmethod - def evaluate(self, dataset: list[EvalData]): - """ - Abstract method to evaluate the dataset. - - This method should be implemented by subclasses to perform the actual - evaluation on the dataset. - - :param dataset: dataset to evaluate - :type dataset: list[EvalData] - """ - raise NotImplementedError() diff --git a/embedchain/embedchain/evaluation/metrics/__init__.py b/embedchain/embedchain/evaluation/metrics/__init__.py deleted file mode 100644 index 95f579005..000000000 --- a/embedchain/embedchain/evaluation/metrics/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .answer_relevancy import AnswerRelevance # noqa: F401 -from .context_relevancy import ContextRelevance # noqa: F401 -from .groundedness import Groundedness # noqa: F401 diff --git a/embedchain/embedchain/evaluation/metrics/answer_relevancy.py b/embedchain/embedchain/evaluation/metrics/answer_relevancy.py deleted file mode 100644 index 3e5c3859e..000000000 --- a/embedchain/embedchain/evaluation/metrics/answer_relevancy.py +++ /dev/null @@ -1,95 +0,0 @@ -import concurrent.futures -import logging -import os -from string import Template -from typing import Optional - -import numpy as np -from openai import OpenAI -from tqdm import tqdm - -from embedchain.config.evaluation.base import AnswerRelevanceConfig -from embedchain.evaluation.base import BaseMetric -from embedchain.utils.evaluation import EvalData, EvalMetric - -logger = logging.getLogger(__name__) - - -class AnswerRelevance(BaseMetric): - """ - Metric for evaluating the relevance of answers. - """ - - def __init__(self, config: Optional[AnswerRelevanceConfig] = AnswerRelevanceConfig()): - super().__init__(name=EvalMetric.ANSWER_RELEVANCY.value) - self.config = config - api_key = self.config.api_key or os.getenv("OPENAI_API_KEY") - if not api_key: - raise ValueError("API key not found. Set 'OPENAI_API_KEY' or pass it in the config.") - self.client = OpenAI(api_key=api_key) - - def _generate_prompt(self, data: EvalData) -> str: - """ - Generates a prompt based on the provided data. - """ - return Template(self.config.prompt).substitute( - num_gen_questions=self.config.num_gen_questions, answer=data.answer - ) - - def _generate_questions(self, prompt: str) -> list[str]: - """ - Generates questions from the prompt. - """ - response = self.client.chat.completions.create( - model=self.config.model, - messages=[{"role": "user", "content": prompt}], - ) - return response.choices[0].message.content.strip().split("\n") - - def _generate_embedding(self, question: str) -> np.ndarray: - """ - Generates the embedding for a question. - """ - response = self.client.embeddings.create( - input=question, - model=self.config.embedder, - ) - return np.array(response.data[0].embedding) - - def _compute_similarity(self, original: np.ndarray, generated: np.ndarray) -> float: - """ - Computes the cosine similarity between two embeddings. - """ - original = original.reshape(1, -1) - norm = np.linalg.norm(original) * np.linalg.norm(generated, axis=1) - return np.dot(generated, original.T).flatten() / norm - - def _compute_score(self, data: EvalData) -> float: - """ - Computes the relevance score for a given data item. - """ - prompt = self._generate_prompt(data) - generated_questions = self._generate_questions(prompt) - original_embedding = self._generate_embedding(data.question) - generated_embeddings = np.array([self._generate_embedding(q) for q in generated_questions]) - similarities = self._compute_similarity(original_embedding, generated_embeddings) - return np.mean(similarities) - - def evaluate(self, dataset: list[EvalData]) -> float: - """ - Evaluates the dataset and returns the average answer relevance score. - """ - results = [] - - with concurrent.futures.ThreadPoolExecutor() as executor: - future_to_data = {executor.submit(self._compute_score, data): data for data in dataset} - for future in tqdm( - concurrent.futures.as_completed(future_to_data), total=len(dataset), desc="Evaluating Answer Relevancy" - ): - data = future_to_data[future] - try: - results.append(future.result()) - except Exception as e: - logger.error(f"Error evaluating answer relevancy for {data}: {e}") - - return np.mean(results) if results else 0.0 diff --git a/embedchain/embedchain/evaluation/metrics/context_relevancy.py b/embedchain/embedchain/evaluation/metrics/context_relevancy.py deleted file mode 100644 index f821713fa..000000000 --- a/embedchain/embedchain/evaluation/metrics/context_relevancy.py +++ /dev/null @@ -1,69 +0,0 @@ -import concurrent.futures -import os -from string import Template -from typing import Optional - -import numpy as np -import pysbd -from openai import OpenAI -from tqdm import tqdm - -from embedchain.config.evaluation.base import ContextRelevanceConfig -from embedchain.evaluation.base import BaseMetric -from embedchain.utils.evaluation import EvalData, EvalMetric - - -class ContextRelevance(BaseMetric): - """ - Metric for evaluating the relevance of context in a dataset. - """ - - def __init__(self, config: Optional[ContextRelevanceConfig] = ContextRelevanceConfig()): - super().__init__(name=EvalMetric.CONTEXT_RELEVANCY.value) - self.config = config - api_key = self.config.api_key or os.getenv("OPENAI_API_KEY") - if not api_key: - raise ValueError("API key not found. Set 'OPENAI_API_KEY' or pass it in the config.") - self.client = OpenAI(api_key=api_key) - self._sbd = pysbd.Segmenter(language=self.config.language, clean=False) - - def _sentence_segmenter(self, text: str) -> list[str]: - """ - Segments the given text into sentences. - """ - return self._sbd.segment(text) - - def _compute_score(self, data: EvalData) -> float: - """ - Computes the context relevance score for a given data item. - """ - original_context = "\n".join(data.contexts) - prompt = Template(self.config.prompt).substitute(context=original_context, question=data.question) - response = self.client.chat.completions.create( - model=self.config.model, messages=[{"role": "user", "content": prompt}] - ) - useful_context = response.choices[0].message.content.strip() - useful_context_sentences = self._sentence_segmenter(useful_context) - original_context_sentences = self._sentence_segmenter(original_context) - - if not original_context_sentences: - return 0.0 - return len(useful_context_sentences) / len(original_context_sentences) - - def evaluate(self, dataset: list[EvalData]) -> float: - """ - Evaluates the dataset and returns the average context relevance score. - """ - scores = [] - - with concurrent.futures.ThreadPoolExecutor() as executor: - futures = [executor.submit(self._compute_score, data) for data in dataset] - for future in tqdm( - concurrent.futures.as_completed(futures), total=len(dataset), desc="Evaluating Context Relevancy" - ): - try: - scores.append(future.result()) - except Exception as e: - print(f"Error during evaluation: {e}") - - return np.mean(scores) if scores else 0.0 diff --git a/embedchain/embedchain/evaluation/metrics/groundedness.py b/embedchain/embedchain/evaluation/metrics/groundedness.py deleted file mode 100644 index 86f3f320e..000000000 --- a/embedchain/embedchain/evaluation/metrics/groundedness.py +++ /dev/null @@ -1,104 +0,0 @@ -import concurrent.futures -import logging -import os -from string import Template -from typing import Optional - -import numpy as np -from openai import OpenAI -from tqdm import tqdm - -from embedchain.config.evaluation.base import GroundednessConfig -from embedchain.evaluation.base import BaseMetric -from embedchain.utils.evaluation import EvalData, EvalMetric - -logger = logging.getLogger(__name__) - - -class Groundedness(BaseMetric): - """ - Metric for groundedness of answer from the given contexts. - """ - - def __init__(self, config: Optional[GroundednessConfig] = None): - super().__init__(name=EvalMetric.GROUNDEDNESS.value) - self.config = config or GroundednessConfig() - api_key = self.config.api_key or os.getenv("OPENAI_API_KEY") - if not api_key: - raise ValueError("Please set the OPENAI_API_KEY environment variable or pass the `api_key` in config.") - self.client = OpenAI(api_key=api_key) - - def _generate_answer_claim_prompt(self, data: EvalData) -> str: - """ - Generate the prompt for the given data. - """ - prompt = Template(self.config.answer_claims_prompt).substitute(question=data.question, answer=data.answer) - return prompt - - def _get_claim_statements(self, prompt: str) -> np.ndarray: - """ - Get claim statements from the answer. - """ - response = self.client.chat.completions.create( - model=self.config.model, - messages=[{"role": "user", "content": f"{prompt}"}], - ) - result = response.choices[0].message.content.strip() - claim_statements = np.array([statement for statement in result.split("\n") if statement]) - return claim_statements - - def _generate_claim_inference_prompt(self, data: EvalData, claim_statements: list[str]) -> str: - """ - Generate the claim inference prompt for the given data and claim statements. - """ - prompt = Template(self.config.claims_inference_prompt).substitute( - context="\n".join(data.contexts), claim_statements="\n".join(claim_statements) - ) - return prompt - - def _get_claim_verdict_scores(self, prompt: str) -> np.ndarray: - """ - Get verdicts for claim statements. - """ - response = self.client.chat.completions.create( - model=self.config.model, - messages=[{"role": "user", "content": f"{prompt}"}], - ) - result = response.choices[0].message.content.strip() - claim_verdicts = result.split("\n") - verdict_score_map = {"1": 1, "0": 0, "-1": np.nan} - verdict_scores = np.array([verdict_score_map[verdict] for verdict in claim_verdicts]) - return verdict_scores - - def _compute_score(self, data: EvalData) -> float: - """ - Compute the groundedness score for a single data point. - """ - answer_claims_prompt = self._generate_answer_claim_prompt(data) - claim_statements = self._get_claim_statements(answer_claims_prompt) - - claim_inference_prompt = self._generate_claim_inference_prompt(data, claim_statements) - verdict_scores = self._get_claim_verdict_scores(claim_inference_prompt) - return np.sum(verdict_scores) / claim_statements.size - - def evaluate(self, dataset: list[EvalData]): - """ - Evaluate the dataset and returns the average groundedness score. - """ - results = [] - - with concurrent.futures.ThreadPoolExecutor() as executor: - future_to_data = {executor.submit(self._compute_score, data): data for data in dataset} - for future in tqdm( - concurrent.futures.as_completed(future_to_data), - total=len(future_to_data), - desc="Evaluating Groundedness", - ): - data = future_to_data[future] - try: - score = future.result() - results.append(score) - except Exception as e: - logger.error(f"Error while evaluating groundedness for data point {data}: {e}") - - return np.mean(results) if results else 0.0 diff --git a/embedchain/embedchain/factory.py b/embedchain/embedchain/factory.py deleted file mode 100644 index 69636286c..000000000 --- a/embedchain/embedchain/factory.py +++ /dev/null @@ -1,122 +0,0 @@ -import importlib - - -def load_class(class_type): - module_path, class_name = class_type.rsplit(".", 1) - module = importlib.import_module(module_path) - return getattr(module, class_name) - - -class LlmFactory: - provider_to_class = { - "anthropic": "embedchain.llm.anthropic.AnthropicLlm", - "azure_openai": "embedchain.llm.azure_openai.AzureOpenAILlm", - "cohere": "embedchain.llm.cohere.CohereLlm", - "together": "embedchain.llm.together.TogetherLlm", - "gpt4all": "embedchain.llm.gpt4all.GPT4ALLLlm", - "ollama": "embedchain.llm.ollama.OllamaLlm", - "huggingface": "embedchain.llm.huggingface.HuggingFaceLlm", - "jina": "embedchain.llm.jina.JinaLlm", - "llama2": "embedchain.llm.llama2.Llama2Llm", - "openai": "embedchain.llm.openai.OpenAILlm", - "vertexai": "embedchain.llm.vertex_ai.VertexAILlm", - "google": "embedchain.llm.google.GoogleLlm", - "aws_bedrock": "embedchain.llm.aws_bedrock.AWSBedrockLlm", - "mistralai": "embedchain.llm.mistralai.MistralAILlm", - "clarifai": "embedchain.llm.clarifai.ClarifaiLlm", - "groq": "embedchain.llm.groq.GroqLlm", - "nvidia": "embedchain.llm.nvidia.NvidiaLlm", - "vllm": "embedchain.llm.vllm.VLLM", - } - provider_to_config_class = { - "embedchain": "embedchain.config.llm.base.BaseLlmConfig", - "openai": "embedchain.config.llm.base.BaseLlmConfig", - "anthropic": "embedchain.config.llm.base.BaseLlmConfig", - } - - @classmethod - def create(cls, provider_name, config_data): - class_type = cls.provider_to_class.get(provider_name) - # Default to embedchain base config if the provider is not in the config map - config_name = "embedchain" if provider_name not in cls.provider_to_config_class else provider_name - config_class_type = cls.provider_to_config_class.get(config_name) - if class_type: - llm_class = load_class(class_type) - llm_config_class = load_class(config_class_type) - return llm_class(config=llm_config_class(**config_data)) - else: - raise ValueError(f"Unsupported Llm provider: {provider_name}") - - -class EmbedderFactory: - provider_to_class = { - "azure_openai": "embedchain.embedder.azure_openai.AzureOpenAIEmbedder", - "gpt4all": "embedchain.embedder.gpt4all.GPT4AllEmbedder", - "huggingface": "embedchain.embedder.huggingface.HuggingFaceEmbedder", - "openai": "embedchain.embedder.openai.OpenAIEmbedder", - "vertexai": "embedchain.embedder.vertexai.VertexAIEmbedder", - "google": "embedchain.embedder.google.GoogleAIEmbedder", - "mistralai": "embedchain.embedder.mistralai.MistralAIEmbedder", - "clarifai": "embedchain.embedder.clarifai.ClarifaiEmbedder", - "nvidia": "embedchain.embedder.nvidia.NvidiaEmbedder", - "cohere": "embedchain.embedder.cohere.CohereEmbedder", - "ollama": "embedchain.embedder.ollama.OllamaEmbedder", - "aws_bedrock": "embedchain.embedder.aws_bedrock.AWSBedrockEmbedder", - } - provider_to_config_class = { - "azure_openai": "embedchain.config.embedder.base.BaseEmbedderConfig", - "google": "embedchain.config.embedder.google.GoogleAIEmbedderConfig", - "gpt4all": "embedchain.config.embedder.base.BaseEmbedderConfig", - "huggingface": "embedchain.config.embedder.base.BaseEmbedderConfig", - "clarifai": "embedchain.config.embedder.base.BaseEmbedderConfig", - "openai": "embedchain.config.embedder.base.BaseEmbedderConfig", - "ollama": "embedchain.config.embedder.ollama.OllamaEmbedderConfig", - "aws_bedrock": "embedchain.config.embedder.aws_bedrock.AWSBedrockEmbedderConfig", - } - - @classmethod - def create(cls, provider_name, config_data): - class_type = cls.provider_to_class.get(provider_name) - # Default to openai config if the provider is not in the config map - config_name = "openai" if provider_name not in cls.provider_to_config_class else provider_name - config_class_type = cls.provider_to_config_class.get(config_name) - if class_type: - embedder_class = load_class(class_type) - embedder_config_class = load_class(config_class_type) - return embedder_class(config=embedder_config_class(**config_data)) - else: - raise ValueError(f"Unsupported Embedder provider: {provider_name}") - - -class VectorDBFactory: - provider_to_class = { - "chroma": "embedchain.vectordb.chroma.ChromaDB", - "elasticsearch": "embedchain.vectordb.elasticsearch.ElasticsearchDB", - "opensearch": "embedchain.vectordb.opensearch.OpenSearchDB", - "lancedb": "embedchain.vectordb.lancedb.LanceDB", - "pinecone": "embedchain.vectordb.pinecone.PineconeDB", - "qdrant": "embedchain.vectordb.qdrant.QdrantDB", - "weaviate": "embedchain.vectordb.weaviate.WeaviateDB", - "zilliz": "embedchain.vectordb.zilliz.ZillizVectorDB", - } - provider_to_config_class = { - "chroma": "embedchain.config.vector_db.chroma.ChromaDbConfig", - "elasticsearch": "embedchain.config.vector_db.elasticsearch.ElasticsearchDBConfig", - "opensearch": "embedchain.config.vector_db.opensearch.OpenSearchDBConfig", - "lancedb": "embedchain.config.vector_db.lancedb.LanceDBConfig", - "pinecone": "embedchain.config.vector_db.pinecone.PineconeDBConfig", - "qdrant": "embedchain.config.vector_db.qdrant.QdrantDBConfig", - "weaviate": "embedchain.config.vector_db.weaviate.WeaviateDBConfig", - "zilliz": "embedchain.config.vector_db.zilliz.ZillizDBConfig", - } - - @classmethod - def create(cls, provider_name, config_data): - class_type = cls.provider_to_class.get(provider_name) - config_class_type = cls.provider_to_config_class.get(provider_name) - if class_type: - embedder_class = load_class(class_type) - embedder_config_class = load_class(config_class_type) - return embedder_class(config=embedder_config_class(**config_data)) - else: - raise ValueError(f"Unsupported Embedder provider: {provider_name}") diff --git a/embedchain/embedchain/helpers/__init__.py b/embedchain/embedchain/helpers/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/helpers/callbacks.py b/embedchain/embedchain/helpers/callbacks.py deleted file mode 100644 index 4847e0fea..000000000 --- a/embedchain/embedchain/helpers/callbacks.py +++ /dev/null @@ -1,73 +0,0 @@ -import queue -from typing import Any, Union - -from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler -from langchain.schema import LLMResult - -STOP_ITEM = "[END]" -""" -This is a special item that is used to signal the end of the stream. -""" - - -class StreamingStdOutCallbackHandlerYield(StreamingStdOutCallbackHandler): - """ - This is a callback handler that yields the tokens as they are generated. - For a usage example, see the :func:`generate` function below. - """ - - q: queue.Queue - """ - The queue to write the tokens to as they are generated. - """ - - def __init__(self, q: queue.Queue) -> None: - """ - Initialize the callback handler. - q: The queue to write the tokens to as they are generated. - """ - super().__init__() - self.q = q - - def on_llm_start(self, serialized: dict[str, Any], prompts: list[str], **kwargs: Any) -> None: - """Run when LLM starts running.""" - with self.q.mutex: - self.q.queue.clear() - - def on_llm_new_token(self, token: str, **kwargs: Any) -> None: - """Run on new LLM token. Only available when streaming is enabled.""" - self.q.put(token) - - def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None: - """Run when LLM ends running.""" - self.q.put(STOP_ITEM) - - def on_llm_error(self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any) -> None: - """Run when LLM errors.""" - self.q.put("%s: %s" % (type(error).__name__, str(error))) - self.q.put(STOP_ITEM) - - -def generate(rq: queue.Queue): - """ - This is a generator that yields the items in the queue until it reaches the stop item. - - Usage example: - ``` - def askQuestion(callback_fn: StreamingStdOutCallbackHandlerYield): - llm = OpenAI(streaming=True, callbacks=[callback_fn]) - return llm.invoke(prompt="Write a poem about a tree.") - - @app.route("/", methods=["GET"]) - def generate_output(): - q = Queue() - callback_fn = StreamingStdOutCallbackHandlerYield(q) - threading.Thread(target=askQuestion, args=(callback_fn,)).start() - return Response(generate(q), mimetype="text/event-stream") - ``` - """ - while True: - result: str = rq.get() - if result == STOP_ITEM or result is None: - break - yield result diff --git a/embedchain/embedchain/helpers/json_serializable.py b/embedchain/embedchain/helpers/json_serializable.py deleted file mode 100644 index 656bb44bc..000000000 --- a/embedchain/embedchain/helpers/json_serializable.py +++ /dev/null @@ -1,198 +0,0 @@ -import json -import logging -from string import Template -from typing import Any, Type, TypeVar, Union - -T = TypeVar("T", bound="JSONSerializable") - -# NOTE: Through inheritance, all of our classes should be children of JSONSerializable. (highest level) -# NOTE: The @register_deserializable decorator should be added to all user facing child classes. (lowest level) - -logger = logging.getLogger(__name__) - - -def register_deserializable(cls: Type[T]) -> Type[T]: - """ - A class decorator to register a class as deserializable. - - When a class is decorated with @register_deserializable, it becomes - a part of the set of classes that the JSONSerializable class can - deserialize. - - Deserialization is in essence loading attributes from a json file. - This decorator is a security measure put in place to make sure that - you don't load attributes that were initially part of another class. - - Example: - @register_deserializable - class ChildClass(JSONSerializable): - def __init__(self, ...): - # initialization logic - - Args: - cls (Type): The class to be registered. - - Returns: - Type: The same class, after registration. - """ - JSONSerializable._register_class_as_deserializable(cls) - return cls - - -class JSONSerializable: - """ - A class to represent a JSON serializable object. - - This class provides methods to serialize and deserialize objects, - as well as to save serialized objects to a file and load them back. - """ - - _deserializable_classes = set() # Contains classes that are whitelisted for deserialization. - - def serialize(self) -> str: - """ - Serialize the object to a JSON-formatted string. - - Returns: - str: A JSON string representation of the object. - """ - try: - return json.dumps(self, default=self._auto_encoder, ensure_ascii=False) - except Exception as e: - logger.error(f"Serialization error: {e}") - return "{}" - - @classmethod - def deserialize(cls, json_str: str) -> Any: - """ - Deserialize a JSON-formatted string to an object. - If it fails, a default class is returned instead. - Note: This *returns* an instance, it's not automatically loaded on the calling class. - - Example: - app = App.deserialize(json_str) - - Args: - json_str (str): A JSON string representation of an object. - - Returns: - Object: The deserialized object. - """ - try: - return json.loads(json_str, object_hook=cls._auto_decoder) - except Exception as e: - logger.error(f"Deserialization error: {e}") - # Return a default instance in case of failure - return cls() - - @staticmethod - def _auto_encoder(obj: Any) -> Union[dict[str, Any], None]: - """ - Automatically encode an object for JSON serialization. - - Args: - obj (Object): The object to be encoded. - - Returns: - dict: A dictionary representation of the object. - """ - if hasattr(obj, "__dict__"): - dct = {} - for key, value in obj.__dict__.items(): - try: - # Recursive: If the value is an instance of a subclass of JSONSerializable, - # serialize it using the JSONSerializable serialize method. - if isinstance(value, JSONSerializable): - serialized_value = value.serialize() - # The value is stored as a serialized string. - dct[key] = json.loads(serialized_value) - # Custom rules (subclass is not json serializable by default) - elif isinstance(value, Template): - dct[key] = {"__type__": "Template", "data": value.template} - # Future custom types we can follow a similar pattern - # elif isinstance(value, SomeOtherType): - # dct[key] = { - # "__type__": "SomeOtherType", - # "data": value.some_method() - # } - # NOTE: Keep in mind that this logic needs to be applied to the decoder too. - else: - json.dumps(value) # Try to serialize the value. - dct[key] = value - except TypeError: - pass # If it fails, simply pass to skip this key-value pair of the dictionary. - - dct["__class__"] = obj.__class__.__name__ - return dct - raise TypeError(f"Object of type {type(obj)} is not JSON serializable") - - @classmethod - def _auto_decoder(cls, dct: dict[str, Any]) -> Any: - """ - Automatically decode a dictionary to an object during JSON deserialization. - - Args: - dct (dict): The dictionary representation of an object. - - Returns: - Object: The decoded object or the original dictionary if decoding is not possible. - """ - class_name = dct.pop("__class__", None) - if class_name: - if not hasattr(cls, "_deserializable_classes"): # Additional safety check - raise AttributeError(f"`{class_name}` has no registry of allowed deserializations.") - if class_name not in {cl.__name__ for cl in cls._deserializable_classes}: - raise KeyError(f"Deserialization of class `{class_name}` is not allowed.") - target_class = next((cl for cl in cls._deserializable_classes if cl.__name__ == class_name), None) - if target_class: - obj = target_class.__new__(target_class) - for key, value in dct.items(): - if isinstance(value, dict) and "__type__" in value: - if value["__type__"] == "Template": - value = Template(value["data"]) - # For future custom types we can follow a similar pattern - # elif value["__type__"] == "SomeOtherType": - # value = SomeOtherType.some_constructor(value["data"]) - default_value = getattr(target_class, key, None) - setattr(obj, key, value or default_value) - return obj - return dct - - def save_to_file(self, filename: str) -> None: - """ - Save the serialized object to a file. - - Args: - filename (str): The path to the file where the object should be saved. - """ - with open(filename, "w", encoding="utf-8") as f: - f.write(self.serialize()) - - @classmethod - def load_from_file(cls, filename: str) -> Any: - """ - Load and deserialize an object from a file. - - Args: - filename (str): The path to the file from which the object should be loaded. - - Returns: - Object: The deserialized object. - """ - with open(filename, "r", encoding="utf-8") as f: - json_str = f.read() - return cls.deserialize(json_str) - - @classmethod - def _register_class_as_deserializable(cls, target_class: Type[T]) -> None: - """ - Register a class as deserializable. This is a classmethod and globally shared. - - This method adds the target class to the set of classes that - can be deserialized. This is a security measure to ensure only - whitelisted classes are deserialized. - - Args: - target_class (Type): The class to be registered. - """ - cls._deserializable_classes.add(target_class) diff --git a/embedchain/embedchain/llm/__init__.py b/embedchain/embedchain/llm/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/llm/anthropic.py b/embedchain/embedchain/llm/anthropic.py deleted file mode 100644 index b5a90a6d5..000000000 --- a/embedchain/embedchain/llm/anthropic.py +++ /dev/null @@ -1,59 +0,0 @@ -import logging -import os -from typing import Any, Optional - -try: - from langchain_anthropic import ChatAnthropic -except ImportError: - raise ImportError("Please install the langchain-anthropic package by running `pip install langchain-anthropic`.") - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - -logger = logging.getLogger(__name__) - - -@register_deserializable -class AnthropicLlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - super().__init__(config=config) - if not self.config.api_key and "ANTHROPIC_API_KEY" not in os.environ: - raise ValueError("Please set the ANTHROPIC_API_KEY environment variable or pass it in the config.") - - def get_llm_model_answer(self, prompt) -> tuple[str, Optional[dict[str, Any]]]: - if self.config.token_usage: - response, token_info = self._get_answer(prompt, self.config) - model_name = "anthropic/" + self.config.model - if model_name not in self.config.model_pricing_map: - raise ValueError( - f"Model {model_name} not found in `model_prices_and_context_window.json`. \ - You can disable token usage by setting `token_usage` to False." - ) - total_cost = ( - self.config.model_pricing_map[model_name]["input_cost_per_token"] * token_info["input_tokens"] - ) + self.config.model_pricing_map[model_name]["output_cost_per_token"] * token_info["output_tokens"] - response_token_info = { - "prompt_tokens": token_info["input_tokens"], - "completion_tokens": token_info["output_tokens"], - "total_tokens": token_info["input_tokens"] + token_info["output_tokens"], - "total_cost": round(total_cost, 10), - "cost_currency": "USD", - } - return response, response_token_info - return self._get_answer(prompt, self.config) - - @staticmethod - def _get_answer(prompt: str, config: BaseLlmConfig) -> str: - api_key = config.api_key or os.getenv("ANTHROPIC_API_KEY") - chat = ChatAnthropic(anthropic_api_key=api_key, temperature=config.temperature, model_name=config.model) - - if config.max_tokens and config.max_tokens != 1000: - logger.warning("Config option `max_tokens` is not supported by this model.") - - messages = BaseLlm._get_messages(prompt, system_prompt=config.system_prompt) - - chat_response = chat.invoke(messages) - if config.token_usage: - return chat_response.content, chat_response.response_metadata["token_usage"] - return chat_response.content diff --git a/embedchain/embedchain/llm/aws_bedrock.py b/embedchain/embedchain/llm/aws_bedrock.py deleted file mode 100644 index 7f916268b..000000000 --- a/embedchain/embedchain/llm/aws_bedrock.py +++ /dev/null @@ -1,57 +0,0 @@ -import os -from typing import Optional - -try: - from langchain_aws import BedrockLLM -except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for AWSBedrock are not installed." "Please install with `pip install langchain_aws`" - ) from None - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - - -@register_deserializable -class AWSBedrockLlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - super().__init__(config) - - def get_llm_model_answer(self, prompt) -> str: - response = self._get_answer(prompt, self.config) - return response - - def _get_answer(self, prompt: str, config: BaseLlmConfig) -> str: - try: - import boto3 - except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for AWSBedrock are not installed." - "Please install with `pip install boto3==1.34.20`." - ) from None - - self.boto_client = boto3.client( - "bedrock-runtime", os.environ.get("AWS_REGION", os.environ.get("AWS_DEFAULT_REGION", "us-east-1")) - ) - - kwargs = { - "model_id": config.model or "amazon.titan-text-express-v1", - "client": self.boto_client, - "model_kwargs": config.model_kwargs - or { - "temperature": config.temperature, - }, - } - - if config.stream: - from langchain.callbacks.streaming_stdout import ( - StreamingStdOutCallbackHandler, - ) - - kwargs["streaming"] = True - kwargs["callbacks"] = [StreamingStdOutCallbackHandler()] - - llm = BedrockLLM(**kwargs) - - return llm.invoke(prompt) diff --git a/embedchain/embedchain/llm/azure_openai.py b/embedchain/embedchain/llm/azure_openai.py deleted file mode 100644 index c219270ac..000000000 --- a/embedchain/embedchain/llm/azure_openai.py +++ /dev/null @@ -1,42 +0,0 @@ -import logging -from typing import Optional - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - -logger = logging.getLogger(__name__) - - -@register_deserializable -class AzureOpenAILlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - super().__init__(config=config) - - def get_llm_model_answer(self, prompt): - return self._get_answer(prompt=prompt, config=self.config) - - @staticmethod - def _get_answer(prompt: str, config: BaseLlmConfig) -> str: - from langchain_openai import AzureChatOpenAI - - if not config.deployment_name: - raise ValueError("Deployment name must be provided for Azure OpenAI") - - chat = AzureChatOpenAI( - deployment_name=config.deployment_name, - openai_api_version=str(config.api_version) if config.api_version else "2024-02-01", - model_name=config.model or "gpt-4o-mini", - temperature=config.temperature, - max_tokens=config.max_tokens, - streaming=config.stream, - http_client=config.http_client, - http_async_client=config.http_async_client, - ) - - if config.top_p and config.top_p != 1: - logger.warning("Config option `top_p` is not supported by this model.") - - messages = BaseLlm._get_messages(prompt, system_prompt=config.system_prompt) - - return chat.invoke(messages).content diff --git a/embedchain/embedchain/llm/base.py b/embedchain/embedchain/llm/base.py deleted file mode 100644 index ace4bb79b..000000000 --- a/embedchain/embedchain/llm/base.py +++ /dev/null @@ -1,350 +0,0 @@ -import logging -import os -from collections.abc import Generator -from typing import Any, Optional - -from langchain.schema import BaseMessage as LCBaseMessage - -from embedchain.config import BaseLlmConfig -from embedchain.config.llm.base import ( - DEFAULT_PROMPT, - DEFAULT_PROMPT_WITH_HISTORY_TEMPLATE, - DEFAULT_PROMPT_WITH_MEM0_MEMORY_TEMPLATE, - DOCS_SITE_PROMPT_TEMPLATE, -) -from embedchain.constants import SQLITE_PATH -from embedchain.core.db.database import init_db, setup_engine -from embedchain.helpers.json_serializable import JSONSerializable -from embedchain.memory.base import ChatHistory -from embedchain.memory.message import ChatMessage - -logger = logging.getLogger(__name__) - - -class BaseLlm(JSONSerializable): - def __init__(self, config: Optional[BaseLlmConfig] = None): - """Initialize a base LLM class - - :param config: LLM configuration option class, defaults to None - :type config: Optional[BaseLlmConfig], optional - """ - if config is None: - self.config = BaseLlmConfig() - else: - self.config = config - - # Initialize the metadata db for the app here since llmfactory needs it for initialization of - # the llm memory - setup_engine(database_uri=os.environ.get("EMBEDCHAIN_DB_URI", f"sqlite:///{SQLITE_PATH}")) - init_db() - - self.memory = ChatHistory() - self.is_docs_site_instance = False - self.history: Any = None - - def get_llm_model_answer(self): - """ - Usually implemented by child class - """ - raise NotImplementedError - - def set_history(self, history: Any): - """ - Provide your own history. - Especially interesting for the query method, which does not internally manage conversation history. - - :param history: History to set - :type history: Any - """ - self.history = history - - def update_history(self, app_id: str, session_id: str = "default"): - """Update class history attribute with history in memory (for chat method)""" - chat_history = self.memory.get(app_id=app_id, session_id=session_id, num_rounds=10) - self.set_history([str(history) for history in chat_history]) - - def add_history( - self, - app_id: str, - question: str, - answer: str, - metadata: Optional[dict[str, Any]] = None, - session_id: str = "default", - ): - chat_message = ChatMessage() - chat_message.add_user_message(question, metadata=metadata) - chat_message.add_ai_message(answer, metadata=metadata) - self.memory.add(app_id=app_id, chat_message=chat_message, session_id=session_id) - self.update_history(app_id=app_id, session_id=session_id) - - def _format_history(self) -> str: - """Format history to be used in prompt - - :return: Formatted history - :rtype: str - """ - return "\n".join(self.history) - - def _format_memories(self, memories: list[dict]) -> str: - """Format memories to be used in prompt - - :param memories: Memories to format - :type memories: list[dict] - :return: Formatted memories - :rtype: str - """ - return "\n".join([memory["text"] for memory in memories]) - - def generate_prompt(self, input_query: str, contexts: list[str], **kwargs: dict[str, Any]) -> str: - """ - Generates a prompt based on the given query and context, ready to be - passed to an LLM - - :param input_query: The query to use. - :type input_query: str - :param contexts: List of similar documents to the query used as context. - :type contexts: list[str] - :return: The prompt - :rtype: str - """ - context_string = " | ".join(contexts) - web_search_result = kwargs.get("web_search_result", "") - memories = kwargs.get("memories", None) - if web_search_result: - context_string = self._append_search_and_context(context_string, web_search_result) - - prompt_contains_history = self.config._validate_prompt_history(self.config.prompt) - if prompt_contains_history: - prompt = self.config.prompt.substitute( - context=context_string, query=input_query, history=self._format_history() or "No history" - ) - elif self.history and not prompt_contains_history: - # History is present, but not included in the prompt. - # check if it's the default prompt without history - if ( - not self.config._validate_prompt_history(self.config.prompt) - and self.config.prompt.template == DEFAULT_PROMPT - ): - if memories: - # swap in the template with Mem0 memory template - prompt = DEFAULT_PROMPT_WITH_MEM0_MEMORY_TEMPLATE.substitute( - context=context_string, - query=input_query, - history=self._format_history(), - memories=self._format_memories(memories), - ) - else: - # swap in the template with history - prompt = DEFAULT_PROMPT_WITH_HISTORY_TEMPLATE.substitute( - context=context_string, query=input_query, history=self._format_history() - ) - else: - # If we can't swap in the default, we still proceed but tell users that the history is ignored. - logger.warning( - "Your bot contains a history, but prompt does not include `$history` key. History is ignored." - ) - prompt = self.config.prompt.substitute(context=context_string, query=input_query) - else: - # basic use case, no history. - prompt = self.config.prompt.substitute(context=context_string, query=input_query) - return prompt - - @staticmethod - def _append_search_and_context(context: str, web_search_result: str) -> str: - """Append web search context to existing context - - :param context: Existing context - :type context: str - :param web_search_result: Web search result - :type web_search_result: str - :return: Concatenated web search result - :rtype: str - """ - return f"{context}\nWeb Search Result: {web_search_result}" - - def get_answer_from_llm(self, prompt: str): - """ - Gets an answer based on the given query and context by passing it - to an LLM. - - :param prompt: Gets an answer based on the given query and context by passing it to an LLM. - :type prompt: str - :return: The answer. - :rtype: _type_ - """ - return self.get_llm_model_answer(prompt) - - @staticmethod - def access_search_and_get_results(input_query: str): - """ - Search the internet for additional context - - :param input_query: search query - :type input_query: str - :return: Search results - :rtype: Unknown - """ - try: - from langchain.tools import DuckDuckGoSearchRun - except ImportError: - raise ImportError( - "Searching requires extra dependencies. Install with `pip install duckduckgo-search==6.1.5`" - ) from None - search = DuckDuckGoSearchRun() - logger.info(f"Access search to get answers for {input_query}") - return search.run(input_query) - - @staticmethod - def _stream_response(answer: Any, token_info: Optional[dict[str, Any]] = None) -> Generator[Any, Any, None]: - """Generator to be used as streaming response - - :param answer: Answer chunk from llm - :type answer: Any - :yield: Answer chunk from llm - :rtype: Generator[Any, Any, None] - """ - streamed_answer = "" - for chunk in answer: - streamed_answer = streamed_answer + chunk - yield chunk - logger.info(f"Answer: {streamed_answer}") - if token_info: - logger.info(f"Token Info: {token_info}") - - def query(self, input_query: str, contexts: list[str], config: BaseLlmConfig = None, dry_run=False, memories=None): - """ - Queries the vector database based on the given input query. - Gets relevant doc based on the query and then passes it to an - LLM as context to get the answer. - - :param input_query: The query to use. - :type input_query: str - :param contexts: Embeddings retrieved from the database to be used as context. - :type contexts: list[str] - :param config: The `BaseLlmConfig` instance to use as configuration options. This is used for one method call. - To persistently use a config, declare it during app init., defaults to None - :type config: Optional[BaseLlmConfig], optional - :param dry_run: A dry run does everything except send the resulting prompt to - the LLM. The purpose is to test the prompt, not the response., defaults to False - :type dry_run: bool, optional - :return: The answer to the query or the dry run result - :rtype: str - """ - try: - if config: - # A config instance passed to this method will only be applied temporarily, for one call. - # So we will save the previous config and restore it at the end of the execution. - # For this we use the serializer. - prev_config = self.config.serialize() - self.config = config - - if config is not None and config.query_type == "Images": - return contexts - - if self.is_docs_site_instance: - self.config.prompt = DOCS_SITE_PROMPT_TEMPLATE - self.config.number_documents = 5 - k = {} - if self.config.online: - k["web_search_result"] = self.access_search_and_get_results(input_query) - k["memories"] = memories - prompt = self.generate_prompt(input_query, contexts, **k) - logger.info(f"Prompt: {prompt}") - if dry_run: - return prompt - - if self.config.token_usage: - answer, token_info = self.get_answer_from_llm(prompt) - else: - answer = self.get_answer_from_llm(prompt) - if isinstance(answer, str): - logger.info(f"Answer: {answer}") - if self.config.token_usage: - return answer, token_info - return answer - else: - if self.config.token_usage: - return self._stream_response(answer, token_info) - return self._stream_response(answer) - finally: - if config: - # Restore previous config - self.config: BaseLlmConfig = BaseLlmConfig.deserialize(prev_config) - - def chat( - self, input_query: str, contexts: list[str], config: BaseLlmConfig = None, dry_run=False, session_id: str = None - ): - """ - Queries the vector database on the given input query. - Gets relevant doc based on the query and then passes it to an - LLM as context to get the answer. - - Maintains the whole conversation in memory. - - :param input_query: The query to use. - :type input_query: str - :param contexts: Embeddings retrieved from the database to be used as context. - :type contexts: list[str] - :param config: The `BaseLlmConfig` instance to use as configuration options. This is used for one method call. - To persistently use a config, declare it during app init., defaults to None - :type config: Optional[BaseLlmConfig], optional - :param dry_run: A dry run does everything except send the resulting prompt to - the LLM. The purpose is to test the prompt, not the response., defaults to False - :type dry_run: bool, optional - :param session_id: Session ID to use for the conversation, defaults to None - :type session_id: str, optional - :return: The answer to the query or the dry run result - :rtype: str - """ - try: - if config: - # A config instance passed to this method will only be applied temporarily, for one call. - # So we will save the previous config and restore it at the end of the execution. - # For this we use the serializer. - prev_config = self.config.serialize() - self.config = config - - if self.is_docs_site_instance: - self.config.prompt = DOCS_SITE_PROMPT_TEMPLATE - self.config.number_documents = 5 - k = {} - if self.config.online: - k["web_search_result"] = self.access_search_and_get_results(input_query) - - prompt = self.generate_prompt(input_query, contexts, **k) - logger.info(f"Prompt: {prompt}") - - if dry_run: - return prompt - - answer, token_info = self.get_answer_from_llm(prompt) - if isinstance(answer, str): - logger.info(f"Answer: {answer}") - return answer, token_info - else: - # this is a streamed response and needs to be handled differently. - return self._stream_response(answer, token_info) - finally: - if config: - # Restore previous config - self.config: BaseLlmConfig = BaseLlmConfig.deserialize(prev_config) - - @staticmethod - def _get_messages(prompt: str, system_prompt: Optional[str] = None) -> list[LCBaseMessage]: - """ - Construct a list of langchain messages - - :param prompt: User prompt - :type prompt: str - :param system_prompt: System prompt, defaults to None - :type system_prompt: Optional[str], optional - :return: List of messages - :rtype: list[BaseMessage] - """ - from langchain.schema import HumanMessage, SystemMessage - - messages = [] - if system_prompt: - messages.append(SystemMessage(content=system_prompt)) - messages.append(HumanMessage(content=prompt)) - return messages diff --git a/embedchain/embedchain/llm/clarifai.py b/embedchain/embedchain/llm/clarifai.py deleted file mode 100644 index 6d87d1b15..000000000 --- a/embedchain/embedchain/llm/clarifai.py +++ /dev/null @@ -1,47 +0,0 @@ -import logging -import os -from typing import Optional - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - - -@register_deserializable -class ClarifaiLlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - super().__init__(config=config) - if not self.config.api_key and "CLARIFAI_PAT" not in os.environ: - raise ValueError("Please set the CLARIFAI_PAT environment variable.") - - def get_llm_model_answer(self, prompt): - return self._get_answer(prompt=prompt, config=self.config) - - @staticmethod - def _get_answer(prompt: str, config: BaseLlmConfig) -> str: - try: - from clarifai.client.model import Model - except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for Clarifai are not installed." - "Please install with `pip install clarifai==10.0.1`" - ) from None - - model_name = config.model - logging.info(f"Using clarifai LLM model: {model_name}") - api_key = config.api_key or os.getenv("CLARIFAI_PAT") - model = Model(url=model_name, pat=api_key) - params = config.model_kwargs - - try: - (params := {}) if config.model_kwargs is None else config.model_kwargs - predict_response = model.predict_by_bytes( - bytes(prompt, "utf-8"), - input_type="text", - inference_params=params, - ) - text = predict_response.outputs[0].data.text.raw - return text - - except Exception as e: - logging.error(f"Predict failed, exception: {e}") diff --git a/embedchain/embedchain/llm/cohere.py b/embedchain/embedchain/llm/cohere.py deleted file mode 100644 index 0a9614b9a..000000000 --- a/embedchain/embedchain/llm/cohere.py +++ /dev/null @@ -1,66 +0,0 @@ -import importlib -import os -from typing import Any, Optional - -from langchain_cohere import ChatCohere - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - - -@register_deserializable -class CohereLlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - try: - importlib.import_module("cohere") - except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for Cohere are not installed." - "Please install with `pip install langchain_cohere==1.16.0`" - ) from None - - super().__init__(config=config) - if not self.config.api_key and "COHERE_API_KEY" not in os.environ: - raise ValueError("Please set the COHERE_API_KEY environment variable or pass it in the config.") - - def get_llm_model_answer(self, prompt) -> tuple[str, Optional[dict[str, Any]]]: - if self.config.system_prompt: - raise ValueError("CohereLlm does not support `system_prompt`") - - if self.config.token_usage: - response, token_info = self._get_answer(prompt, self.config) - model_name = "cohere/" + self.config.model - if model_name not in self.config.model_pricing_map: - raise ValueError( - f"Model {model_name} not found in `model_prices_and_context_window.json`. \ - You can disable token usage by setting `token_usage` to False." - ) - total_cost = ( - self.config.model_pricing_map[model_name]["input_cost_per_token"] * token_info["input_tokens"] - ) + self.config.model_pricing_map[model_name]["output_cost_per_token"] * token_info["output_tokens"] - response_token_info = { - "prompt_tokens": token_info["input_tokens"], - "completion_tokens": token_info["output_tokens"], - "total_tokens": token_info["input_tokens"] + token_info["output_tokens"], - "total_cost": round(total_cost, 10), - "cost_currency": "USD", - } - return response, response_token_info - return self._get_answer(prompt, self.config) - - @staticmethod - def _get_answer(prompt: str, config: BaseLlmConfig) -> str: - api_key = config.api_key or os.environ["COHERE_API_KEY"] - kwargs = { - "model_name": config.model or "command-r", - "temperature": config.temperature, - "max_tokens": config.max_tokens, - "together_api_key": api_key, - } - - chat = ChatCohere(**kwargs) - chat_response = chat.invoke(prompt) - if config.token_usage: - return chat_response.content, chat_response.response_metadata["token_count"] - return chat_response.content diff --git a/embedchain/embedchain/llm/google.py b/embedchain/embedchain/llm/google.py deleted file mode 100644 index c0002fa99..000000000 --- a/embedchain/embedchain/llm/google.py +++ /dev/null @@ -1,62 +0,0 @@ -import logging -import os -from collections.abc import Generator -from typing import Any, Optional, Union - -try: - import google.generativeai as genai -except ImportError: - raise ImportError("GoogleLlm requires extra dependencies. Install with `pip install google-generativeai`") from None - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - -logger = logging.getLogger(__name__) - - -@register_deserializable -class GoogleLlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - super().__init__(config) - if not self.config.api_key and "GOOGLE_API_KEY" not in os.environ: - raise ValueError("Please set the GOOGLE_API_KEY environment variable or pass it in the config.") - - api_key = self.config.api_key or os.getenv("GOOGLE_API_KEY") - genai.configure(api_key=api_key) - - def get_llm_model_answer(self, prompt): - if self.config.system_prompt: - raise ValueError("GoogleLlm does not support `system_prompt`") - response = self._get_answer(prompt) - return response - - def _get_answer(self, prompt: str) -> Union[str, Generator[Any, Any, None]]: - model_name = self.config.model or "gemini-pro" - logger.info(f"Using Google LLM model: {model_name}") - model = genai.GenerativeModel(model_name=model_name) - - generation_config_params = { - "candidate_count": 1, - "max_output_tokens": self.config.max_tokens, - "temperature": self.config.temperature or 0.5, - } - - if 0.0 <= self.config.top_p <= 1.0: - generation_config_params["top_p"] = self.config.top_p - else: - raise ValueError("`top_p` must be > 0.0 and < 1.0") - - generation_config = genai.types.GenerationConfig(**generation_config_params) - - response = model.generate_content( - prompt, - generation_config=generation_config, - stream=self.config.stream, - ) - if self.config.stream: - # TODO: Implement streaming - response.resolve() - return response.text - else: - return response.text diff --git a/embedchain/embedchain/llm/gpt4all.py b/embedchain/embedchain/llm/gpt4all.py deleted file mode 100644 index 76062b08b..000000000 --- a/embedchain/embedchain/llm/gpt4all.py +++ /dev/null @@ -1,67 +0,0 @@ -import os -from collections.abc import Iterable -from pathlib import Path -from typing import Optional, Union - -from langchain.callbacks.stdout import StdOutCallbackHandler -from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - - -@register_deserializable -class GPT4ALLLlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - super().__init__(config=config) - if self.config.model is None: - self.config.model = "orca-mini-3b-gguf2-q4_0.gguf" - self.instance = GPT4ALLLlm._get_instance(self.config.model) - self.instance.streaming = self.config.stream - - def get_llm_model_answer(self, prompt): - return self._get_answer(prompt=prompt, config=self.config) - - @staticmethod - def _get_instance(model): - try: - from langchain_community.llms.gpt4all import GPT4All as LangchainGPT4All - except ModuleNotFoundError: - raise ModuleNotFoundError( - "The GPT4All python package is not installed. Please install it with `pip install --upgrade embedchain[opensource]`" # noqa E501 - ) from None - - model_path = Path(model).expanduser() - if os.path.isabs(model_path): - if os.path.exists(model_path): - return LangchainGPT4All(model=str(model_path)) - else: - raise ValueError(f"Model does not exist at {model_path=}") - else: - return LangchainGPT4All(model=model, allow_download=True) - - def _get_answer(self, prompt: str, config: BaseLlmConfig) -> Union[str, Iterable]: - if config.model and config.model != self.config.model: - raise RuntimeError( - "GPT4ALLLlm does not support switching models at runtime. Please create a new app instance." - ) - - messages = [] - if config.system_prompt: - messages.append(config.system_prompt) - messages.append(prompt) - kwargs = { - "temp": config.temperature, - "max_tokens": config.max_tokens, - } - if config.top_p: - kwargs["top_p"] = config.top_p - - callbacks = [StreamingStdOutCallbackHandler()] if config.stream else [StdOutCallbackHandler()] - - response = self.instance.generate(prompts=messages, callbacks=callbacks, **kwargs) - answer = "" - for generations in response.generations: - answer += " ".join(map(lambda generation: generation.text, generations)) - return answer diff --git a/embedchain/embedchain/llm/groq.py b/embedchain/embedchain/llm/groq.py deleted file mode 100644 index 3f18d3da9..000000000 --- a/embedchain/embedchain/llm/groq.py +++ /dev/null @@ -1,67 +0,0 @@ -import os -from typing import Any, Optional - -from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler -from langchain.schema import HumanMessage, SystemMessage - -try: - from langchain_groq import ChatGroq -except ImportError: - raise ImportError("Groq requires extra dependencies. Install with `pip install langchain-groq`") from None - - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - - -@register_deserializable -class GroqLlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - super().__init__(config=config) - if not self.config.api_key and "GROQ_API_KEY" not in os.environ: - raise ValueError("Please set the GROQ_API_KEY environment variable or pass it in the config.") - - def get_llm_model_answer(self, prompt) -> tuple[str, Optional[dict[str, Any]]]: - if self.config.token_usage: - response, token_info = self._get_answer(prompt, self.config) - model_name = "groq/" + self.config.model - if model_name not in self.config.model_pricing_map: - raise ValueError( - f"Model {model_name} not found in `model_prices_and_context_window.json`. \ - You can disable token usage by setting `token_usage` to False." - ) - total_cost = ( - self.config.model_pricing_map[model_name]["input_cost_per_token"] * token_info["prompt_tokens"] - ) + self.config.model_pricing_map[model_name]["output_cost_per_token"] * token_info["completion_tokens"] - response_token_info = { - "prompt_tokens": token_info["prompt_tokens"], - "completion_tokens": token_info["completion_tokens"], - "total_tokens": token_info["prompt_tokens"] + token_info["completion_tokens"], - "total_cost": round(total_cost, 10), - "cost_currency": "USD", - } - return response, response_token_info - return self._get_answer(prompt, self.config) - - def _get_answer(self, prompt: str, config: BaseLlmConfig) -> str: - messages = [] - if config.system_prompt: - messages.append(SystemMessage(content=config.system_prompt)) - messages.append(HumanMessage(content=prompt)) - api_key = config.api_key or os.environ["GROQ_API_KEY"] - kwargs = { - "model_name": config.model or "mixtral-8x7b-32768", - "temperature": config.temperature, - "groq_api_key": api_key, - } - if config.stream: - callbacks = config.callbacks if config.callbacks else [StreamingStdOutCallbackHandler()] - chat = ChatGroq(**kwargs, streaming=config.stream, callbacks=callbacks, api_key=api_key) - else: - chat = ChatGroq(**kwargs) - - chat_response = chat.invoke(prompt) - if self.config.token_usage: - return chat_response.content, chat_response.response_metadata["token_usage"] - return chat_response.content diff --git a/embedchain/embedchain/llm/huggingface.py b/embedchain/embedchain/llm/huggingface.py deleted file mode 100644 index 28767b07b..000000000 --- a/embedchain/embedchain/llm/huggingface.py +++ /dev/null @@ -1,99 +0,0 @@ -import importlib -import logging -import os -from typing import Optional - -from langchain_community.llms.huggingface_endpoint import HuggingFaceEndpoint -from langchain_community.llms.huggingface_hub import HuggingFaceHub -from langchain_community.llms.huggingface_pipeline import HuggingFacePipeline - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - -logger = logging.getLogger(__name__) - - -@register_deserializable -class HuggingFaceLlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - try: - importlib.import_module("huggingface_hub") - except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for HuggingFaceHub are not installed." - "Please install with `pip install huggingface-hub==0.23.0`" - ) from None - - super().__init__(config=config) - if not self.config.api_key and "HUGGINGFACE_ACCESS_TOKEN" not in os.environ: - raise ValueError("Please set the HUGGINGFACE_ACCESS_TOKEN environment variable or pass it in the config.") - - def get_llm_model_answer(self, prompt): - if self.config.system_prompt: - raise ValueError("HuggingFaceLlm does not support `system_prompt`") - return HuggingFaceLlm._get_answer(prompt=prompt, config=self.config) - - @staticmethod - def _get_answer(prompt: str, config: BaseLlmConfig) -> str: - # If the user wants to run the model locally, they can do so by setting the `local` flag to True - if config.model and config.local: - return HuggingFaceLlm._from_pipeline(prompt=prompt, config=config) - elif config.model: - return HuggingFaceLlm._from_model(prompt=prompt, config=config) - elif config.endpoint: - return HuggingFaceLlm._from_endpoint(prompt=prompt, config=config) - else: - raise ValueError("Either `model` or `endpoint` must be set in config") - - @staticmethod - def _from_model(prompt: str, config: BaseLlmConfig) -> str: - model_kwargs = { - "temperature": config.temperature or 0.1, - "max_new_tokens": config.max_tokens, - } - - if 0.0 < config.top_p < 1.0: - model_kwargs["top_p"] = config.top_p - else: - raise ValueError("`top_p` must be > 0.0 and < 1.0") - - model = config.model - api_key = config.api_key or os.getenv("HUGGINGFACE_ACCESS_TOKEN") - logger.info(f"Using HuggingFaceHub with model {model}") - llm = HuggingFaceHub( - huggingfacehub_api_token=api_key, - repo_id=model, - model_kwargs=model_kwargs, - ) - return llm.invoke(prompt) - - @staticmethod - def _from_endpoint(prompt: str, config: BaseLlmConfig) -> str: - api_key = config.api_key or os.getenv("HUGGINGFACE_ACCESS_TOKEN") - llm = HuggingFaceEndpoint( - huggingfacehub_api_token=api_key, - endpoint_url=config.endpoint, - task="text-generation", - model_kwargs=config.model_kwargs, - ) - return llm.invoke(prompt) - - @staticmethod - def _from_pipeline(prompt: str, config: BaseLlmConfig) -> str: - model_kwargs = { - "temperature": config.temperature or 0.1, - "max_new_tokens": config.max_tokens, - } - - if 0.0 < config.top_p < 1.0: - model_kwargs["top_p"] = config.top_p - else: - raise ValueError("`top_p` must be > 0.0 and < 1.0") - - llm = HuggingFacePipeline.from_model_id( - model_id=config.model, - task="text-generation", - pipeline_kwargs=model_kwargs, - ) - return llm.invoke(prompt) diff --git a/embedchain/embedchain/llm/jina.py b/embedchain/embedchain/llm/jina.py deleted file mode 100644 index ac3a0e76f..000000000 --- a/embedchain/embedchain/llm/jina.py +++ /dev/null @@ -1,45 +0,0 @@ -import os -from typing import Optional - -from langchain.schema import HumanMessage, SystemMessage -from langchain_community.chat_models import JinaChat - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - - -@register_deserializable -class JinaLlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - super().__init__(config=config) - if not self.config.api_key and "JINACHAT_API_KEY" not in os.environ: - raise ValueError("Please set the JINACHAT_API_KEY environment variable or pass it in the config.") - - def get_llm_model_answer(self, prompt): - response = JinaLlm._get_answer(prompt, self.config) - return response - - @staticmethod - def _get_answer(prompt: str, config: BaseLlmConfig) -> str: - messages = [] - if config.system_prompt: - messages.append(SystemMessage(content=config.system_prompt)) - messages.append(HumanMessage(content=prompt)) - kwargs = { - "temperature": config.temperature, - "max_tokens": config.max_tokens, - "jinachat_api_key": config.api_key or os.environ["JINACHAT_API_KEY"], - "model_kwargs": {}, - } - if config.top_p: - kwargs["model_kwargs"]["top_p"] = config.top_p - if config.stream: - from langchain.callbacks.streaming_stdout import ( - StreamingStdOutCallbackHandler, - ) - - chat = JinaChat(**kwargs, streaming=config.stream, callbacks=[StreamingStdOutCallbackHandler()]) - else: - chat = JinaChat(**kwargs) - return chat(messages).content diff --git a/embedchain/embedchain/llm/llama2.py b/embedchain/embedchain/llm/llama2.py deleted file mode 100644 index 8a82f3f75..000000000 --- a/embedchain/embedchain/llm/llama2.py +++ /dev/null @@ -1,53 +0,0 @@ -import importlib -import os -from typing import Optional - -from langchain_community.llms.replicate import Replicate - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - - -@register_deserializable -class Llama2Llm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - try: - importlib.import_module("replicate") - except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for Llama2 are not installed." - 'Please install with `pip install --upgrade "embedchain[llama2]"`' - ) from None - - # Set default config values specific to this llm - if not config: - config = BaseLlmConfig() - # Add variables to this block that have a default value in the parent class - config.max_tokens = 500 - config.temperature = 0.75 - # Add variables that are `none` by default to this block. - if not config.model: - config.model = ( - "a16z-infra/llama13b-v2-chat:df7690f1994d94e96ad9d568eac121aecf50684a0b0963b25a41cc40061269e5" - ) - - super().__init__(config=config) - if not self.config.api_key and "REPLICATE_API_TOKEN" not in os.environ: - raise ValueError("Please set the REPLICATE_API_TOKEN environment variable or pass it in the config.") - - def get_llm_model_answer(self, prompt): - # TODO: Move the model and other inputs into config - if self.config.system_prompt: - raise ValueError("Llama2 does not support `system_prompt`") - api_key = self.config.api_key or os.getenv("REPLICATE_API_TOKEN") - llm = Replicate( - model=self.config.model, - replicate_api_token=api_key, - input={ - "temperature": self.config.temperature, - "max_length": self.config.max_tokens, - "top_p": self.config.top_p, - }, - ) - return llm.invoke(prompt) diff --git a/embedchain/embedchain/llm/mistralai.py b/embedchain/embedchain/llm/mistralai.py deleted file mode 100644 index 92af3be17..000000000 --- a/embedchain/embedchain/llm/mistralai.py +++ /dev/null @@ -1,72 +0,0 @@ -import os -from typing import Any, Optional - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - - -@register_deserializable -class MistralAILlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - super().__init__(config) - if not self.config.api_key and "MISTRAL_API_KEY" not in os.environ: - raise ValueError("Please set the MISTRAL_API_KEY environment variable or pass it in the config.") - - def get_llm_model_answer(self, prompt) -> tuple[str, Optional[dict[str, Any]]]: - if self.config.token_usage: - response, token_info = self._get_answer(prompt, self.config) - model_name = "mistralai/" + self.config.model - if model_name not in self.config.model_pricing_map: - raise ValueError( - f"Model {model_name} not found in `model_prices_and_context_window.json`. \ - You can disable token usage by setting `token_usage` to False." - ) - total_cost = ( - self.config.model_pricing_map[model_name]["input_cost_per_token"] * token_info["prompt_tokens"] - ) + self.config.model_pricing_map[model_name]["output_cost_per_token"] * token_info["completion_tokens"] - response_token_info = { - "prompt_tokens": token_info["prompt_tokens"], - "completion_tokens": token_info["completion_tokens"], - "total_tokens": token_info["prompt_tokens"] + token_info["completion_tokens"], - "total_cost": round(total_cost, 10), - "cost_currency": "USD", - } - return response, response_token_info - return self._get_answer(prompt, self.config) - - @staticmethod - def _get_answer(prompt: str, config: BaseLlmConfig): - try: - from langchain_core.messages import HumanMessage, SystemMessage - from langchain_mistralai.chat_models import ChatMistralAI - except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for MistralAI are not installed." - 'Please install with `pip install --upgrade "embedchain[mistralai]"`' - ) from None - - api_key = config.api_key or os.getenv("MISTRAL_API_KEY") - client = ChatMistralAI(mistral_api_key=api_key) - messages = [] - if config.system_prompt: - messages.append(SystemMessage(content=config.system_prompt)) - messages.append(HumanMessage(content=prompt)) - kwargs = { - "model": config.model or "mistral-tiny", - "temperature": config.temperature, - "max_tokens": config.max_tokens, - "top_p": config.top_p, - } - - # TODO: Add support for streaming - if config.stream: - answer = "" - for chunk in client.stream(**kwargs, input=messages): - answer += chunk.content - return answer - else: - chat_response = client.invoke(**kwargs, input=messages) - if config.token_usage: - return chat_response.content, chat_response.response_metadata["token_usage"] - return chat_response.content diff --git a/embedchain/embedchain/llm/nvidia.py b/embedchain/embedchain/llm/nvidia.py deleted file mode 100644 index 71c045b6a..000000000 --- a/embedchain/embedchain/llm/nvidia.py +++ /dev/null @@ -1,68 +0,0 @@ -import os -from collections.abc import Iterable -from typing import Any, Optional, Union - -from langchain.callbacks.manager import CallbackManager -from langchain.callbacks.stdout import StdOutCallbackHandler -from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler - -try: - from langchain_nvidia_ai_endpoints import ChatNVIDIA -except ImportError: - raise ImportError( - "NVIDIA AI endpoints requires extra dependencies. Install with `pip install langchain-nvidia-ai-endpoints`" - ) from None - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - - -@register_deserializable -class NvidiaLlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - super().__init__(config=config) - if not self.config.api_key and "NVIDIA_API_KEY" not in os.environ: - raise ValueError("Please set the NVIDIA_API_KEY environment variable or pass it in the config.") - - def get_llm_model_answer(self, prompt) -> tuple[str, Optional[dict[str, Any]]]: - if self.config.token_usage: - response, token_info = self._get_answer(prompt, self.config) - model_name = "nvidia/" + self.config.model - if model_name not in self.config.model_pricing_map: - raise ValueError( - f"Model {model_name} not found in `model_prices_and_context_window.json`. \ - You can disable token usage by setting `token_usage` to False." - ) - total_cost = ( - self.config.model_pricing_map[model_name]["input_cost_per_token"] * token_info["input_tokens"] - ) + self.config.model_pricing_map[model_name]["output_cost_per_token"] * token_info["output_tokens"] - response_token_info = { - "prompt_tokens": token_info["input_tokens"], - "completion_tokens": token_info["output_tokens"], - "total_tokens": token_info["input_tokens"] + token_info["output_tokens"], - "total_cost": round(total_cost, 10), - "cost_currency": "USD", - } - return response, response_token_info - return self._get_answer(prompt, self.config) - - @staticmethod - def _get_answer(prompt: str, config: BaseLlmConfig) -> Union[str, Iterable]: - callback_manager = [StreamingStdOutCallbackHandler()] if config.stream else [StdOutCallbackHandler()] - model_kwargs = config.model_kwargs or {} - labels = model_kwargs.get("labels", None) - params = {"model": config.model, "nvidia_api_key": config.api_key or os.getenv("NVIDIA_API_KEY")} - if config.system_prompt: - params["system_prompt"] = config.system_prompt - if config.temperature: - params["temperature"] = config.temperature - if config.top_p: - params["top_p"] = config.top_p - if labels: - params["labels"] = labels - llm = ChatNVIDIA(**params, callback_manager=CallbackManager(callback_manager)) - chat_response = llm.invoke(prompt) if labels is None else llm.invoke(prompt, labels=labels) - if config.token_usage: - return chat_response.content, chat_response.response_metadata["token_usage"] - return chat_response.content diff --git a/embedchain/embedchain/llm/ollama.py b/embedchain/embedchain/llm/ollama.py deleted file mode 100644 index e34ff38e1..000000000 --- a/embedchain/embedchain/llm/ollama.py +++ /dev/null @@ -1,54 +0,0 @@ -import logging -from collections.abc import Iterable -from typing import Optional, Union - -from langchain.callbacks.manager import CallbackManager -from langchain.callbacks.stdout import StdOutCallbackHandler -from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler -from langchain_community.llms.ollama import Ollama - -try: - from ollama import Client -except ImportError: - raise ImportError("Ollama requires extra dependencies. Install with `pip install ollama`") from None - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - -logger = logging.getLogger(__name__) - - -@register_deserializable -class OllamaLlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - super().__init__(config=config) - if self.config.model is None: - self.config.model = "llama2" - - client = Client(host=config.base_url) - local_models = client.list()["models"] - if not any(model.get("name") == self.config.model for model in local_models): - logger.info(f"Pulling {self.config.model} from Ollama!") - client.pull(self.config.model) - - def get_llm_model_answer(self, prompt): - return self._get_answer(prompt=prompt, config=self.config) - - @staticmethod - def _get_answer(prompt: str, config: BaseLlmConfig) -> Union[str, Iterable]: - if config.stream: - callbacks = config.callbacks if config.callbacks else [StreamingStdOutCallbackHandler()] - else: - callbacks = [StdOutCallbackHandler()] - - llm = Ollama( - model=config.model, - system=config.system_prompt, - temperature=config.temperature, - top_p=config.top_p, - callback_manager=CallbackManager(callbacks), - base_url=config.base_url, - ) - - return llm.invoke(prompt) diff --git a/embedchain/embedchain/llm/openai.py b/embedchain/embedchain/llm/openai.py deleted file mode 100644 index ace146118..000000000 --- a/embedchain/embedchain/llm/openai.py +++ /dev/null @@ -1,120 +0,0 @@ -import json -import os -import warnings -from typing import Any, Callable, Dict, Optional, Type, Union - -from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler -from langchain.schema import BaseMessage, HumanMessage, SystemMessage -from langchain_core.tools import BaseTool -from langchain_openai import ChatOpenAI -from pydantic import BaseModel - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - - -@register_deserializable -class OpenAILlm(BaseLlm): - def __init__( - self, - config: Optional[BaseLlmConfig] = None, - tools: Optional[Union[Dict[str, Any], Type[BaseModel], Callable[..., Any], BaseTool]] = None, - ): - self.tools = tools - super().__init__(config=config) - - def get_llm_model_answer(self, prompt) -> tuple[str, Optional[dict[str, Any]]]: - if self.config.token_usage: - response, token_info = self._get_answer(prompt, self.config) - model_name = "openai/" + self.config.model - if model_name not in self.config.model_pricing_map: - raise ValueError( - f"Model {model_name} not found in `model_prices_and_context_window.json`. \ - You can disable token usage by setting `token_usage` to False." - ) - total_cost = ( - self.config.model_pricing_map[model_name]["input_cost_per_token"] * token_info["prompt_tokens"] - ) + self.config.model_pricing_map[model_name]["output_cost_per_token"] * token_info["completion_tokens"] - response_token_info = { - "prompt_tokens": token_info["prompt_tokens"], - "completion_tokens": token_info["completion_tokens"], - "total_tokens": token_info["prompt_tokens"] + token_info["completion_tokens"], - "total_cost": round(total_cost, 10), - "cost_currency": "USD", - } - return response, response_token_info - - return self._get_answer(prompt, self.config) - - def _get_answer(self, prompt: str, config: BaseLlmConfig) -> str: - messages = [] - if config.system_prompt: - messages.append(SystemMessage(content=config.system_prompt)) - messages.append(HumanMessage(content=prompt)) - kwargs = { - "model": config.model or "gpt-4o-mini", - "temperature": config.temperature, - "max_tokens": config.max_tokens, - "model_kwargs": config.model_kwargs or {}, - } - api_key = config.api_key or os.environ["OPENAI_API_KEY"] - base_url = ( - config.base_url - or os.getenv("OPENAI_API_BASE") - or os.getenv("OPENAI_BASE_URL") - or "https://api.openai.com/v1" - ) - if os.environ.get("OPENAI_API_BASE"): - warnings.warn( - "The environment variable 'OPENAI_API_BASE' is deprecated and will be removed in the 0.1.140. " - "Please use 'OPENAI_BASE_URL' instead.", - DeprecationWarning - ) - - if config.top_p: - kwargs["top_p"] = config.top_p - if config.default_headers: - kwargs["default_headers"] = config.default_headers - if config.stream: - callbacks = config.callbacks if config.callbacks else [StreamingStdOutCallbackHandler()] - chat = ChatOpenAI( - **kwargs, - streaming=config.stream, - callbacks=callbacks, - api_key=api_key, - base_url=base_url, - http_client=config.http_client, - http_async_client=config.http_async_client, - ) - else: - chat = ChatOpenAI( - **kwargs, - api_key=api_key, - base_url=base_url, - http_client=config.http_client, - http_async_client=config.http_async_client, - ) - if self.tools: - return self._query_function_call(chat, self.tools, messages) - - chat_response = chat.invoke(messages) - if self.config.token_usage: - return chat_response.content, chat_response.response_metadata["token_usage"] - return chat_response.content - - def _query_function_call( - self, - chat: ChatOpenAI, - tools: Optional[Union[Dict[str, Any], Type[BaseModel], Callable[..., Any], BaseTool]], - messages: list[BaseMessage], - ) -> str: - from langchain.output_parsers.openai_tools import JsonOutputToolsParser - from langchain_core.utils.function_calling import convert_to_openai_tool - - openai_tools = [convert_to_openai_tool(tools)] - chat = chat.bind(tools=openai_tools).pipe(JsonOutputToolsParser()) - try: - return json.dumps(chat.invoke(messages)[0]) - except IndexError: - return "Input could not be mapped to the function!" diff --git a/embedchain/embedchain/llm/together.py b/embedchain/embedchain/llm/together.py deleted file mode 100644 index 84443a712..000000000 --- a/embedchain/embedchain/llm/together.py +++ /dev/null @@ -1,71 +0,0 @@ -import importlib -import os -from typing import Any, Optional - -try: - from langchain_together import ChatTogether -except ImportError: - raise ImportError( - "Please install the langchain_together package by running `pip install langchain_together==0.1.3`." - ) - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - - -@register_deserializable -class TogetherLlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - try: - importlib.import_module("together") - except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for Together are not installed." - 'Please install with `pip install --upgrade "embedchain[together]"`' - ) from None - - super().__init__(config=config) - if not self.config.api_key and "TOGETHER_API_KEY" not in os.environ: - raise ValueError("Please set the TOGETHER_API_KEY environment variable or pass it in the config.") - - def get_llm_model_answer(self, prompt) -> tuple[str, Optional[dict[str, Any]]]: - if self.config.system_prompt: - raise ValueError("TogetherLlm does not support `system_prompt`") - - if self.config.token_usage: - response, token_info = self._get_answer(prompt, self.config) - model_name = "together/" + self.config.model - if model_name not in self.config.model_pricing_map: - raise ValueError( - f"Model {model_name} not found in `model_prices_and_context_window.json`. \ - You can disable token usage by setting `token_usage` to False." - ) - total_cost = ( - self.config.model_pricing_map[model_name]["input_cost_per_token"] * token_info["prompt_tokens"] - ) + self.config.model_pricing_map[model_name]["output_cost_per_token"] * token_info["completion_tokens"] - response_token_info = { - "prompt_tokens": token_info["prompt_tokens"], - "completion_tokens": token_info["completion_tokens"], - "total_tokens": token_info["prompt_tokens"] + token_info["completion_tokens"], - "total_cost": round(total_cost, 10), - "cost_currency": "USD", - } - return response, response_token_info - return self._get_answer(prompt, self.config) - - @staticmethod - def _get_answer(prompt: str, config: BaseLlmConfig) -> str: - api_key = config.api_key or os.environ["TOGETHER_API_KEY"] - kwargs = { - "model_name": config.model or "mixtral-8x7b-32768", - "temperature": config.temperature, - "max_tokens": config.max_tokens, - "together_api_key": api_key, - } - - chat = ChatTogether(**kwargs) - chat_response = chat.invoke(prompt) - if config.token_usage: - return chat_response.content, chat_response.response_metadata["token_usage"] - return chat_response.content diff --git a/embedchain/embedchain/llm/vertex_ai.py b/embedchain/embedchain/llm/vertex_ai.py deleted file mode 100644 index 55c31a1ad..000000000 --- a/embedchain/embedchain/llm/vertex_ai.py +++ /dev/null @@ -1,68 +0,0 @@ -import importlib -import logging -from typing import Any, Optional - -from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler -from langchain_google_vertexai import ChatVertexAI - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - -logger = logging.getLogger(__name__) - - -@register_deserializable -class VertexAILlm(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - try: - importlib.import_module("vertexai") - except ModuleNotFoundError: - raise ModuleNotFoundError( - "The required dependencies for VertexAI are not installed." - 'Please install with `pip install --upgrade "embedchain[vertexai]"`' - ) from None - super().__init__(config=config) - - def get_llm_model_answer(self, prompt) -> tuple[str, Optional[dict[str, Any]]]: - if self.config.token_usage: - response, token_info = self._get_answer(prompt, self.config) - model_name = "vertexai/" + self.config.model - if model_name not in self.config.model_pricing_map: - raise ValueError( - f"Model {model_name} not found in `model_prices_and_context_window.json`. \ - You can disable token usage by setting `token_usage` to False." - ) - total_cost = ( - self.config.model_pricing_map[model_name]["input_cost_per_token"] * token_info["prompt_token_count"] - ) + self.config.model_pricing_map[model_name]["output_cost_per_token"] * token_info[ - "candidates_token_count" - ] - response_token_info = { - "prompt_tokens": token_info["prompt_token_count"], - "completion_tokens": token_info["candidates_token_count"], - "total_tokens": token_info["prompt_token_count"] + token_info["candidates_token_count"], - "total_cost": round(total_cost, 10), - "cost_currency": "USD", - } - return response, response_token_info - return self._get_answer(prompt, self.config) - - @staticmethod - def _get_answer(prompt: str, config: BaseLlmConfig) -> str: - if config.top_p and config.top_p != 1: - logger.warning("Config option `top_p` is not supported by this model.") - - if config.stream: - callbacks = config.callbacks if config.callbacks else [StreamingStdOutCallbackHandler()] - llm = ChatVertexAI( - temperature=config.temperature, model=config.model, callbacks=callbacks, streaming=config.stream - ) - else: - llm = ChatVertexAI(temperature=config.temperature, model=config.model) - - messages = VertexAILlm._get_messages(prompt) - chat_response = llm.invoke(messages) - if config.token_usage: - return chat_response.content, chat_response.response_metadata["usage_metadata"] - return chat_response.content diff --git a/embedchain/embedchain/llm/vllm.py b/embedchain/embedchain/llm/vllm.py deleted file mode 100644 index 88a8e2ad2..000000000 --- a/embedchain/embedchain/llm/vllm.py +++ /dev/null @@ -1,40 +0,0 @@ -from typing import Iterable, Optional, Union - -from langchain.callbacks.manager import CallbackManager -from langchain.callbacks.stdout import StdOutCallbackHandler -from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler -from langchain_community.llms import VLLM as BaseVLLM - -from embedchain.config import BaseLlmConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.llm.base import BaseLlm - - -@register_deserializable -class VLLM(BaseLlm): - def __init__(self, config: Optional[BaseLlmConfig] = None): - super().__init__(config=config) - if self.config.model is None: - self.config.model = "mosaicml/mpt-7b" - - def get_llm_model_answer(self, prompt): - return self._get_answer(prompt=prompt, config=self.config) - - @staticmethod - def _get_answer(prompt: str, config: BaseLlmConfig) -> Union[str, Iterable]: - callback_manager = [StreamingStdOutCallbackHandler()] if config.stream else [StdOutCallbackHandler()] - - # Prepare the arguments for BaseVLLM - llm_args = { - "model": config.model, - "temperature": config.temperature, - "top_p": config.top_p, - "callback_manager": CallbackManager(callback_manager), - } - - # Add model_kwargs if they are not None - if config.model_kwargs is not None: - llm_args.update(config.model_kwargs) - - llm = BaseVLLM(**llm_args) - return llm.invoke(prompt) diff --git a/embedchain/embedchain/loaders/__init__.py b/embedchain/embedchain/loaders/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/loaders/audio.py b/embedchain/embedchain/loaders/audio.py deleted file mode 100644 index 6b2b69cf2..000000000 --- a/embedchain/embedchain/loaders/audio.py +++ /dev/null @@ -1,53 +0,0 @@ -import hashlib -import os - -import validators - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader - -try: - from deepgram import DeepgramClient, PrerecordedOptions -except ImportError: - raise ImportError( - "Audio file requires extra dependencies. Install with `pip install deepgram-sdk==3.2.7`" - ) from None - - -@register_deserializable -class AudioLoader(BaseLoader): - def __init__(self): - if not os.environ.get("DEEPGRAM_API_KEY"): - raise ValueError("DEEPGRAM_API_KEY is not set") - - DG_KEY = os.environ.get("DEEPGRAM_API_KEY") - self.client = DeepgramClient(DG_KEY) - - def load_data(self, url: str): - """Load data from a audio file or URL.""" - - options = PrerecordedOptions( - model="nova-2", - smart_format=True, - ) - if validators.url(url): - source = {"url": url} - response = self.client.listen.prerecorded.v("1").transcribe_url(source, options) - else: - with open(url, "rb") as audio: - source = {"buffer": audio} - response = self.client.listen.prerecorded.v("1").transcribe_file(source, options) - content = response["results"]["channels"][0]["alternatives"][0]["transcript"] - - doc_id = hashlib.sha256((content + url).encode()).hexdigest() - metadata = {"url": url} - - return { - "doc_id": doc_id, - "data": [ - { - "content": content, - "meta_data": metadata, - } - ], - } diff --git a/embedchain/embedchain/loaders/base_loader.py b/embedchain/embedchain/loaders/base_loader.py deleted file mode 100644 index 9dccfd539..000000000 --- a/embedchain/embedchain/loaders/base_loader.py +++ /dev/null @@ -1,14 +0,0 @@ -from typing import Any, Optional - -from embedchain.helpers.json_serializable import JSONSerializable - - -class BaseLoader(JSONSerializable): - def __init__(self): - pass - - def load_data(self, url, **kwargs: Optional[dict[str, Any]]): - """ - Implemented by child classes - """ - pass diff --git a/embedchain/embedchain/loaders/beehiiv.py b/embedchain/embedchain/loaders/beehiiv.py deleted file mode 100644 index 12d0fe4a9..000000000 --- a/embedchain/embedchain/loaders/beehiiv.py +++ /dev/null @@ -1,107 +0,0 @@ -import hashlib -import logging -import time -from xml.etree import ElementTree - -import requests - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import is_readable - -logger = logging.getLogger(__name__) - - -@register_deserializable -class BeehiivLoader(BaseLoader): - """ - This loader is used to load data from Beehiiv URLs. - """ - - def load_data(self, url: str): - try: - from bs4 import BeautifulSoup - from bs4.builder import ParserRejectedMarkup - except ImportError: - raise ImportError( - "Beehiiv requires extra dependencies. Install with `pip install beautifulsoup4==4.12.3`" - ) from None - - if not url.endswith("sitemap.xml"): - url = url + "/sitemap.xml" - - output = [] - # we need to set this as a header to avoid 403 - headers = { - "User-Agent": ( - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) " - "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 " - "Safari/537.36" - ), - } - response = requests.get(url, headers=headers) - try: - response.raise_for_status() - except requests.exceptions.HTTPError as e: - raise ValueError( - f""" - Failed to load {url}: {e}. Please use the root substack URL. For example, https://example.substack.com - """ - ) - - try: - ElementTree.fromstring(response.content) - except ElementTree.ParseError: - raise ValueError( - f""" - Failed to parse {url}. Please use the root substack URL. For example, https://example.substack.com - """ - ) - soup = BeautifulSoup(response.text, "xml") - links = [link.text for link in soup.find_all("loc") if link.parent.name == "url" and "/p/" in link.text] - if len(links) == 0: - links = [link.text for link in soup.find_all("loc") if "/p/" in link.text] - - doc_id = hashlib.sha256((" ".join(links) + url).encode()).hexdigest() - - def serialize_response(soup: BeautifulSoup): - data = {} - - h1_el = soup.find("h1") - if h1_el is not None: - data["title"] = h1_el.text - - description_el = soup.find("meta", {"name": "description"}) - if description_el is not None: - data["description"] = description_el["content"] - - content_el = soup.find("div", {"id": "content-blocks"}) - if content_el is not None: - data["content"] = content_el.text - - return data - - def load_link(link: str): - try: - beehiiv_data = requests.get(link, headers=headers) - beehiiv_data.raise_for_status() - - soup = BeautifulSoup(beehiiv_data.text, "html.parser") - data = serialize_response(soup) - data = str(data) - if is_readable(data): - return data - else: - logger.warning(f"Page is not readable (too many invalid characters): {link}") - except ParserRejectedMarkup as e: - logger.error(f"Failed to parse {link}: {e}") - return None - - for link in links: - data = load_link(link) - if data: - output.append({"content": data, "meta_data": {"url": link}}) - # TODO: allow users to configure this - time.sleep(1.0) # added to avoid rate limiting - - return {"doc_id": doc_id, "data": output} diff --git a/embedchain/embedchain/loaders/csv.py b/embedchain/embedchain/loaders/csv.py deleted file mode 100644 index 2714d5759..000000000 --- a/embedchain/embedchain/loaders/csv.py +++ /dev/null @@ -1,49 +0,0 @@ -import csv -import hashlib -from io import StringIO -from urllib.parse import urlparse - -import requests - -from embedchain.loaders.base_loader import BaseLoader - - -class CsvLoader(BaseLoader): - @staticmethod - def _detect_delimiter(first_line): - delimiters = [",", "\t", ";", "|"] - counts = {delimiter: first_line.count(delimiter) for delimiter in delimiters} - return max(counts, key=counts.get) - - @staticmethod - def _get_file_content(content): - url = urlparse(content) - if all([url.scheme, url.netloc]) and url.scheme not in ["file", "http", "https"]: - raise ValueError("Not a valid URL.") - - if url.scheme in ["http", "https"]: - response = requests.get(content) - response.raise_for_status() - return StringIO(response.text) - elif url.scheme == "file": - path = url.path - return open(path, newline="", encoding="utf-8") # Open the file using the path from the URI - else: - return open(content, newline="", encoding="utf-8") # Treat content as a regular file path - - @staticmethod - def load_data(content): - """Load a csv file with headers. Each line is a document""" - result = [] - lines = [] - with CsvLoader._get_file_content(content) as file: - first_line = file.readline() - delimiter = CsvLoader._detect_delimiter(first_line) - file.seek(0) # Reset the file pointer to the start - reader = csv.DictReader(file, delimiter=delimiter) - for i, row in enumerate(reader): - line = ", ".join([f"{field}: {value}" for field, value in row.items()]) - lines.append(line) - result.append({"content": line, "meta_data": {"url": content, "row": i + 1}}) - doc_id = hashlib.sha256((content + " ".join(lines)).encode()).hexdigest() - return {"doc_id": doc_id, "data": result} diff --git a/embedchain/embedchain/loaders/directory_loader.py b/embedchain/embedchain/loaders/directory_loader.py deleted file mode 100644 index 5903813b5..000000000 --- a/embedchain/embedchain/loaders/directory_loader.py +++ /dev/null @@ -1,63 +0,0 @@ -import hashlib -import logging -from pathlib import Path -from typing import Any, Optional - -from embedchain.config import AddConfig -from embedchain.data_formatter.data_formatter import DataFormatter -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader -from embedchain.loaders.text_file import TextFileLoader -from embedchain.utils.misc import detect_datatype - -logger = logging.getLogger(__name__) - - -@register_deserializable -class DirectoryLoader(BaseLoader): - """Load data from a directory.""" - - def __init__(self, config: Optional[dict[str, Any]] = None): - super().__init__() - config = config or {} - self.recursive = config.get("recursive", True) - self.extensions = config.get("extensions", None) - self.errors = [] - - def load_data(self, path: str): - directory_path = Path(path) - if not directory_path.is_dir(): - raise ValueError(f"Invalid path: {path}") - - logger.info(f"Loading data from directory: {path}") - data_list = self._process_directory(directory_path) - doc_id = hashlib.sha256((str(data_list) + str(directory_path)).encode()).hexdigest() - - for error in self.errors: - logger.warning(error) - - return {"doc_id": doc_id, "data": data_list} - - def _process_directory(self, directory_path: Path): - data_list = [] - for file_path in directory_path.rglob("*") if self.recursive else directory_path.glob("*"): - # don't include dotfiles - if file_path.name.startswith("."): - continue - if file_path.is_file() and (not self.extensions or any(file_path.suffix == ext for ext in self.extensions)): - loader = self._predict_loader(file_path) - data_list.extend(loader.load_data(str(file_path))["data"]) - elif file_path.is_dir(): - logger.info(f"Loading data from directory: {file_path}") - return data_list - - def _predict_loader(self, file_path: Path) -> BaseLoader: - try: - data_type = detect_datatype(str(file_path)) - config = AddConfig() - return DataFormatter(data_type=data_type, config=config)._get_loader( - data_type=data_type, config=config.loader, loader=None - ) - except Exception as e: - self.errors.append(f"Error processing {file_path}: {e}") - return TextFileLoader() diff --git a/embedchain/embedchain/loaders/discord.py b/embedchain/embedchain/loaders/discord.py deleted file mode 100644 index 807a3d00c..000000000 --- a/embedchain/embedchain/loaders/discord.py +++ /dev/null @@ -1,152 +0,0 @@ -import hashlib -import logging -import os - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader - -logger = logging.getLogger(__name__) - - -@register_deserializable -class DiscordLoader(BaseLoader): - """ - Load data from a Discord Channel ID. - """ - - def __init__(self): - if not os.environ.get("DISCORD_TOKEN"): - raise ValueError("DISCORD_TOKEN is not set") - - self.token = os.environ.get("DISCORD_TOKEN") - - @staticmethod - def _format_message(message): - return { - "message_id": message.id, - "content": message.content, - "author": { - "id": message.author.id, - "name": message.author.name, - "discriminator": message.author.discriminator, - }, - "created_at": message.created_at.isoformat(), - "attachments": [ - { - "id": attachment.id, - "filename": attachment.filename, - "size": attachment.size, - "url": attachment.url, - "proxy_url": attachment.proxy_url, - "height": attachment.height, - "width": attachment.width, - } - for attachment in message.attachments - ], - "embeds": [ - { - "title": embed.title, - "type": embed.type, - "description": embed.description, - "url": embed.url, - "timestamp": embed.timestamp.isoformat(), - "color": embed.color, - "footer": { - "text": embed.footer.text, - "icon_url": embed.footer.icon_url, - "proxy_icon_url": embed.footer.proxy_icon_url, - }, - "image": { - "url": embed.image.url, - "proxy_url": embed.image.proxy_url, - "height": embed.image.height, - "width": embed.image.width, - }, - "thumbnail": { - "url": embed.thumbnail.url, - "proxy_url": embed.thumbnail.proxy_url, - "height": embed.thumbnail.height, - "width": embed.thumbnail.width, - }, - "video": { - "url": embed.video.url, - "height": embed.video.height, - "width": embed.video.width, - }, - "provider": { - "name": embed.provider.name, - "url": embed.provider.url, - }, - "author": { - "name": embed.author.name, - "url": embed.author.url, - "icon_url": embed.author.icon_url, - "proxy_icon_url": embed.author.proxy_icon_url, - }, - "fields": [ - { - "name": field.name, - "value": field.value, - "inline": field.inline, - } - for field in embed.fields - ], - } - for embed in message.embeds - ], - } - - def load_data(self, channel_id: str): - """Load data from a Discord Channel ID.""" - import discord - - messages = [] - - class DiscordClient(discord.Client): - async def on_ready(self) -> None: - logger.info("Logged on as {0}!".format(self.user)) - try: - channel = self.get_channel(int(channel_id)) - if not isinstance(channel, discord.TextChannel): - raise ValueError( - f"Channel {channel_id} is not a text channel. " "Only text channels are supported for now." - ) - threads = {} - - for thread in channel.threads: - threads[thread.id] = thread - - async for message in channel.history(limit=None): - messages.append(DiscordLoader._format_message(message)) - if message.id in threads: - async for thread_message in threads[message.id].history(limit=None): - messages.append(DiscordLoader._format_message(thread_message)) - - except Exception as e: - logger.error(e) - await self.close() - finally: - await self.close() - - intents = discord.Intents.default() - intents.message_content = True - client = DiscordClient(intents=intents) - client.run(self.token) - - metadata = { - "url": channel_id, - } - - messages = str(messages) - - doc_id = hashlib.sha256((messages + channel_id).encode()).hexdigest() - - return { - "doc_id": doc_id, - "data": [ - { - "content": messages, - "meta_data": metadata, - } - ], - } diff --git a/embedchain/embedchain/loaders/discourse.py b/embedchain/embedchain/loaders/discourse.py deleted file mode 100644 index 65c1dd756..000000000 --- a/embedchain/embedchain/loaders/discourse.py +++ /dev/null @@ -1,79 +0,0 @@ -import hashlib -import logging -import time -from typing import Any, Optional - -import requests - -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import clean_string - -logger = logging.getLogger(__name__) - - -class DiscourseLoader(BaseLoader): - def __init__(self, config: Optional[dict[str, Any]] = None): - super().__init__() - if not config: - raise ValueError( - "DiscourseLoader requires a config. Check the documentation for the correct format - `https://docs.embedchain.ai/components/data-sources/discourse`" # noqa: E501 - ) - - self.domain = config.get("domain") - if not self.domain: - raise ValueError( - "DiscourseLoader requires a domain. Check the documentation for the correct format - `https://docs.embedchain.ai/components/data-sources/discourse`" # noqa: E501 - ) - - def _check_query(self, query): - if not query or not isinstance(query, str): - raise ValueError( - "DiscourseLoader requires a query. Check the documentation for the correct format - `https://docs.embedchain.ai/components/data-sources/discourse`" # noqa: E501 - ) - - def _load_post(self, post_id): - post_url = f"{self.domain}posts/{post_id}.json" - response = requests.get(post_url) - try: - response.raise_for_status() - except Exception as e: - logger.error(f"Failed to load post {post_id}: {e}") - return - response_data = response.json() - post_contents = clean_string(response_data.get("raw")) - metadata = { - "url": post_url, - "created_at": response_data.get("created_at", ""), - "username": response_data.get("username", ""), - "topic_slug": response_data.get("topic_slug", ""), - "score": response_data.get("score", ""), - } - data = { - "content": post_contents, - "meta_data": metadata, - } - return data - - def load_data(self, query): - self._check_query(query) - data = [] - data_contents = [] - logger.info(f"Searching data on discourse url: {self.domain}, for query: {query}") - search_url = f"{self.domain}search.json?q={query}" - response = requests.get(search_url) - try: - response.raise_for_status() - except Exception as e: - raise ValueError(f"Failed to search query {query}: {e}") - response_data = response.json() - post_ids = response_data.get("grouped_search_result").get("post_ids") - for id in post_ids: - post_data = self._load_post(id) - if post_data: - data.append(post_data) - data_contents.append(post_data.get("content")) - # Sleep for 0.4 sec, to avoid rate limiting. Check `https://meta.discourse.org/t/api-rate-limits/208405/6` - time.sleep(0.4) - doc_id = hashlib.sha256((query + ", ".join(data_contents)).encode()).hexdigest() - response_data = {"doc_id": doc_id, "data": data} - return response_data diff --git a/embedchain/embedchain/loaders/docs_site_loader.py b/embedchain/embedchain/loaders/docs_site_loader.py deleted file mode 100644 index b9831a9cd..000000000 --- a/embedchain/embedchain/loaders/docs_site_loader.py +++ /dev/null @@ -1,119 +0,0 @@ -import hashlib -import logging -from urllib.parse import urljoin, urlparse - -import requests - -try: - from bs4 import BeautifulSoup -except ImportError: - raise ImportError( - "DocsSite requires extra dependencies. Install with `pip install beautifulsoup4==4.12.3`" - ) from None - - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader - -logger = logging.getLogger(__name__) - - -@register_deserializable -class DocsSiteLoader(BaseLoader): - def __init__(self): - self.visited_links = set() - - def _get_child_links_recursive(self, url): - if url in self.visited_links: - return - - parsed_url = urlparse(url) - base_url = f"{parsed_url.scheme}://{parsed_url.netloc}" - current_path = parsed_url.path - - response = requests.get(url) - if response.status_code != 200: - logger.info(f"Failed to fetch the website: {response.status_code}") - return - - soup = BeautifulSoup(response.text, "html.parser") - all_links = (link.get("href") for link in soup.find_all("a", href=True)) - - child_links = (link for link in all_links if link.startswith(current_path) and link != current_path) - - absolute_paths = set(urljoin(base_url, link) for link in child_links) - - self.visited_links.update(absolute_paths) - - [self._get_child_links_recursive(link) for link in absolute_paths if link not in self.visited_links] - - def _get_all_urls(self, url): - self.visited_links = set() - self._get_child_links_recursive(url) - urls = [link for link in self.visited_links if urlparse(link).netloc == urlparse(url).netloc] - return urls - - @staticmethod - def _load_data_from_url(url: str) -> list: - response = requests.get(url) - if response.status_code != 200: - logger.info(f"Failed to fetch the website: {response.status_code}") - return [] - - soup = BeautifulSoup(response.content, "html.parser") - selectors = [ - "article.bd-article", - 'article[role="main"]', - "div.md-content", - 'div[role="main"]', - "div.container", - "div.section", - "article", - "main", - ] - - output = [] - for selector in selectors: - element = soup.select_one(selector) - if element: - content = element.prettify() - break - else: - content = soup.get_text() - - soup = BeautifulSoup(content, "html.parser") - ignored_tags = [ - "nav", - "aside", - "form", - "header", - "noscript", - "svg", - "canvas", - "footer", - "script", - "style", - ] - for tag in soup(ignored_tags): - tag.decompose() - - content = " ".join(soup.stripped_strings) - output.append( - { - "content": content, - "meta_data": {"url": url}, - } - ) - - return output - - def load_data(self, url): - all_urls = self._get_all_urls(url) - output = [] - for u in all_urls: - output.extend(self._load_data_from_url(u)) - doc_id = hashlib.sha256((" ".join(all_urls) + url).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": output, - } diff --git a/embedchain/embedchain/loaders/docx_file.py b/embedchain/embedchain/loaders/docx_file.py deleted file mode 100644 index 219bb9914..000000000 --- a/embedchain/embedchain/loaders/docx_file.py +++ /dev/null @@ -1,26 +0,0 @@ -import hashlib - -try: - from langchain_community.document_loaders import Docx2txtLoader -except ImportError: - raise ImportError("Docx file requires extra dependencies. Install with `pip install docx2txt==0.8`") from None -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader - - -@register_deserializable -class DocxFileLoader(BaseLoader): - def load_data(self, url): - """Load data from a .docx file.""" - loader = Docx2txtLoader(url) - output = [] - data = loader.load() - content = data[0].page_content - metadata = data[0].metadata - metadata["url"] = "local" - output.append({"content": content, "meta_data": metadata}) - doc_id = hashlib.sha256((content + url).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": output, - } diff --git a/embedchain/embedchain/loaders/dropbox.py b/embedchain/embedchain/loaders/dropbox.py deleted file mode 100644 index 1fbaf2897..000000000 --- a/embedchain/embedchain/loaders/dropbox.py +++ /dev/null @@ -1,79 +0,0 @@ -import hashlib -import os - -from dropbox.files import FileMetadata - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader -from embedchain.loaders.directory_loader import DirectoryLoader - - -@register_deserializable -class DropboxLoader(BaseLoader): - def __init__(self): - access_token = os.environ.get("DROPBOX_ACCESS_TOKEN") - if not access_token: - raise ValueError("Please set the `DROPBOX_ACCESS_TOKEN` environment variable.") - try: - from dropbox import Dropbox, exceptions - except ImportError: - raise ImportError("Dropbox requires extra dependencies. Install with `pip install dropbox==11.36.2`") - - try: - dbx = Dropbox(access_token) - dbx.users_get_current_account() - self.dbx = dbx - except exceptions.AuthError as ex: - raise ValueError("Invalid Dropbox access token. Please verify your token and try again.") from ex - - def _download_folder(self, path: str, local_root: str) -> list[FileMetadata]: - """Download a folder from Dropbox and save it preserving the directory structure.""" - entries = self.dbx.files_list_folder(path).entries - for entry in entries: - local_path = os.path.join(local_root, entry.name) - if isinstance(entry, FileMetadata): - self.dbx.files_download_to_file(local_path, f"{path}/{entry.name}") - else: - os.makedirs(local_path, exist_ok=True) - self._download_folder(f"{path}/{entry.name}", local_path) - return entries - - def _generate_dir_id_from_all_paths(self, path: str) -> str: - """Generate a unique ID for a directory based on all of its paths.""" - entries = self.dbx.files_list_folder(path).entries - paths = [f"{path}/{entry.name}" for entry in entries] - return hashlib.sha256("".join(paths).encode()).hexdigest() - - def load_data(self, path: str): - """Load data from a Dropbox URL, preserving the folder structure.""" - root_dir = f"dropbox_{self._generate_dir_id_from_all_paths(path)}" - os.makedirs(root_dir, exist_ok=True) - - for entry in self.dbx.files_list_folder(path).entries: - local_path = os.path.join(root_dir, entry.name) - if isinstance(entry, FileMetadata): - self.dbx.files_download_to_file(local_path, f"{path}/{entry.name}") - else: - os.makedirs(local_path, exist_ok=True) - self._download_folder(f"{path}/{entry.name}", local_path) - - dir_loader = DirectoryLoader() - data = dir_loader.load_data(root_dir)["data"] - - # Clean up - self._clean_directory(root_dir) - - return { - "doc_id": hashlib.sha256(path.encode()).hexdigest(), - "data": data, - } - - def _clean_directory(self, dir_path): - """Recursively delete a directory and its contents.""" - for item in os.listdir(dir_path): - item_path = os.path.join(dir_path, item) - if os.path.isdir(item_path): - self._clean_directory(item_path) - else: - os.remove(item_path) - os.rmdir(dir_path) diff --git a/embedchain/embedchain/loaders/excel_file.py b/embedchain/embedchain/loaders/excel_file.py deleted file mode 100644 index 585415770..000000000 --- a/embedchain/embedchain/loaders/excel_file.py +++ /dev/null @@ -1,41 +0,0 @@ -import hashlib -import importlib.util - -try: - import unstructured # noqa: F401 - from langchain_community.document_loaders import UnstructuredExcelLoader -except ImportError: - raise ImportError( - 'Excel file requires extra dependencies. Install with `pip install "unstructured[local-inference, all-docs]"`' - ) from None - -if importlib.util.find_spec("openpyxl") is None and importlib.util.find_spec("xlrd") is None: - raise ImportError("Excel file requires extra dependencies. Install with `pip install openpyxl xlrd`") from None - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import clean_string - - -@register_deserializable -class ExcelFileLoader(BaseLoader): - def load_data(self, excel_url): - """Load data from a Excel file.""" - loader = UnstructuredExcelLoader(excel_url) - pages = loader.load_and_split() - - data = [] - for page in pages: - content = page.page_content - content = clean_string(content) - - metadata = page.metadata - metadata["url"] = excel_url - - data.append({"content": content, "meta_data": metadata}) - - doc_id = hashlib.sha256((content + excel_url).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": data, - } diff --git a/embedchain/embedchain/loaders/github.py b/embedchain/embedchain/loaders/github.py deleted file mode 100644 index dac7241e0..000000000 --- a/embedchain/embedchain/loaders/github.py +++ /dev/null @@ -1,312 +0,0 @@ -import concurrent.futures -import hashlib -import logging -import re -import shlex -from typing import Any, Optional - -from tqdm import tqdm - -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import clean_string - -GITHUB_URL = "https://github.com" -GITHUB_API_URL = "https://api.github.com" - -VALID_SEARCH_TYPES = set(["code", "repo", "pr", "issue", "discussion", "branch", "file"]) - - -class GithubLoader(BaseLoader): - """Load data from GitHub search query.""" - - def __init__(self, config: Optional[dict[str, Any]] = None): - super().__init__() - if not config: - raise ValueError( - "GithubLoader requires a personal access token to use github api. Check - `https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic`" # noqa: E501 - ) - - try: - from github import Github - except ImportError as e: - raise ValueError( - "GithubLoader requires extra dependencies. \ - Install with `pip install gitpython==3.1.38 PyGithub==1.59.1`" - ) from e - - self.config = config - token = config.get("token") - if not token: - raise ValueError( - "GithubLoader requires a personal access token to use github api. Check - `https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic`" # noqa: E501 - ) - - try: - self.client = Github(token) - except Exception as e: - logging.error(f"GithubLoader failed to initialize client: {e}") - self.client = None - - def _github_search_code(self, query: str): - """Search GitHub code.""" - data = [] - results = self.client.search_code(query) - for result in tqdm(results, total=results.totalCount, desc="Loading code files from github"): - url = result.html_url - logging.info(f"Added data from url: {url}") - content = result.decoded_content.decode("utf-8") - metadata = { - "url": url, - } - data.append( - { - "content": clean_string(content), - "meta_data": metadata, - } - ) - return data - - def _get_github_repo_data(self, repo_name: str, branch_name: str = None, file_path: str = None) -> list[dict]: - """Get file contents from Repo""" - data = [] - - repo = self.client.get_repo(repo_name) - repo_contents = repo.get_contents("") - - if branch_name: - repo_contents = repo.get_contents("", ref=branch_name) - if file_path: - repo_contents = [repo.get_contents(file_path)] - - with tqdm(desc="Loading files:", unit="item") as progress_bar: - while repo_contents: - file_content = repo_contents.pop(0) - if file_content.type == "dir": - try: - repo_contents.extend(repo.get_contents(file_content.path)) - except Exception: - logging.warning(f"Failed to read directory: {file_content.path}") - progress_bar.update(1) - continue - else: - try: - file_text = file_content.decoded_content.decode() - except Exception: - logging.warning(f"Failed to read file: {file_content.path}") - progress_bar.update(1) - continue - - file_path = file_content.path - data.append( - { - "content": clean_string(file_text), - "meta_data": { - "path": file_path, - }, - } - ) - - progress_bar.update(1) - - return data - - def _github_search_repo(self, query: str) -> list[dict]: - """Search GitHub repo.""" - - logging.info(f"Searching github repos with query: {query}") - updated_query = query.split(":")[-1] - data = self._get_github_repo_data(updated_query) - return data - - def _github_search_issues_and_pr(self, query: str, type: str) -> list[dict]: - """Search GitHub issues and PRs.""" - data = [] - - query = f"{query} is:{type}" - logging.info(f"Searching github for query: {query}") - - results = self.client.search_issues(query) - - logging.info(f"Total results: {results.totalCount}") - for result in tqdm(results, total=results.totalCount, desc=f"Loading {type} from github"): - url = result.html_url - title = result.title - body = result.body - if not body: - logging.warning(f"Skipping issue because empty content for: {url}") - continue - labels = " ".join([label.name for label in result.labels]) - issue_comments = result.get_comments() - comments = [] - comments_created_at = [] - for comment in issue_comments: - comments_created_at.append(str(comment.created_at)) - comments.append(f"{comment.user.name}:{comment.body}") - content = "\n".join([title, labels, body, *comments]) - metadata = { - "url": url, - "created_at": str(result.created_at), - "comments_created_at": " ".join(comments_created_at), - } - data.append( - { - "content": clean_string(content), - "meta_data": metadata, - } - ) - return data - - # need to test more for discussion - def _github_search_discussions(self, query: str): - """Search GitHub discussions.""" - data = [] - - query = f"{query} is:discussion" - logging.info(f"Searching github repo for query: {query}") - repos_results = self.client.search_repositories(query) - logging.info(f"Total repos found: {repos_results.totalCount}") - for repo_result in tqdm(repos_results, total=repos_results.totalCount, desc="Loading discussions from github"): - teams = repo_result.get_teams() - for team in teams: - team_discussions = team.get_discussions() - for discussion in team_discussions: - url = discussion.html_url - title = discussion.title - body = discussion.body - if not body: - logging.warning(f"Skipping discussion because empty content for: {url}") - continue - comments = [] - comments_created_at = [] - print("Discussion comments: ", discussion.comments_url) - content = "\n".join([title, body, *comments]) - metadata = { - "url": url, - "created_at": str(discussion.created_at), - "comments_created_at": " ".join(comments_created_at), - } - data.append( - { - "content": clean_string(content), - "meta_data": metadata, - } - ) - return data - - def _get_github_repo_branch(self, query: str, type: str) -> list[dict]: - """Get file contents for specific branch""" - - logging.info(f"Searching github repo for query: {query} is:{type}") - pattern = r"repo:(\S+) name:(\S+)" - match = re.search(pattern, query) - - if match: - repo_name = match.group(1) - branch_name = match.group(2) - else: - raise ValueError( - f"Repository name and Branch name not found, instead found this \ - Repo: {repo_name}, Branch: {branch_name}" - ) - - data = self._get_github_repo_data(repo_name=repo_name, branch_name=branch_name) - return data - - def _get_github_repo_file(self, query: str, type: str) -> list[dict]: - """Get specific file content""" - - logging.info(f"Searching github repo for query: {query} is:{type}") - pattern = r"repo:(\S+) path:(\S+)" - match = re.search(pattern, query) - - if match: - repo_name = match.group(1) - file_path = match.group(2) - else: - raise ValueError( - f"Repository name and File name not found, instead found this Repo: {repo_name}, File: {file_path}" - ) - - data = self._get_github_repo_data(repo_name=repo_name, file_path=file_path) - return data - - def _search_github_data(self, search_type: str, query: str): - """Search github data.""" - if search_type == "code": - data = self._github_search_code(query) - elif search_type == "repo": - data = self._github_search_repo(query) - elif search_type == "issue": - data = self._github_search_issues_and_pr(query, search_type) - elif search_type == "pr": - data = self._github_search_issues_and_pr(query, search_type) - elif search_type == "branch": - data = self._get_github_repo_branch(query, search_type) - elif search_type == "file": - data = self._get_github_repo_file(query, search_type) - elif search_type == "discussion": - raise ValueError("GithubLoader does not support searching discussions yet.") - else: - raise NotImplementedError(f"{search_type} not supported") - - return data - - @staticmethod - def _get_valid_github_query(query: str): - """Check if query is valid and return search types and valid GitHub query.""" - query_terms = shlex.split(query) - # query must provide repo to load data from - if len(query_terms) < 1 or "repo:" not in query: - raise ValueError( - "GithubLoader requires a search query with `repo:` term. Refer docs - `https://docs.embedchain.ai/data-sources/github`" # noqa: E501 - ) - - github_query = [] - types = set() - type_pattern = r"type:([a-zA-Z,]+)" - for term in query_terms: - term_match = re.search(type_pattern, term) - if term_match: - search_types = term_match.group(1).split(",") - types.update(search_types) - else: - github_query.append(term) - - # query must provide search type - if len(types) == 0: - raise ValueError( - "GithubLoader requires a search query with `type:` term. Refer docs - `https://docs.embedchain.ai/data-sources/github`" # noqa: E501 - ) - - for search_type in search_types: - if search_type not in VALID_SEARCH_TYPES: - raise ValueError( - f"Invalid search type: {search_type}. Valid types are: {', '.join(VALID_SEARCH_TYPES)}" - ) - - query = " ".join(github_query) - - return types, query - - def load_data(self, search_query: str, max_results: int = 1000): - """Load data from GitHub search query.""" - - if not self.client: - raise ValueError( - "GithubLoader client is not initialized, data will not be loaded. Refer docs - `https://docs.embedchain.ai/data-sources/github`" # noqa: E501 - ) - - search_types, query = self._get_valid_github_query(search_query) - logging.info(f"Searching github for query: {query}, with types: {', '.join(search_types)}") - - data = [] - - with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor: - futures_map = executor.map(self._search_github_data, search_types, [query] * len(search_types)) - for search_data in tqdm(futures_map, total=len(search_types), desc="Searching data from github"): - data.extend(search_data) - - return { - "doc_id": hashlib.sha256(query.encode()).hexdigest(), - "data": data, - } diff --git a/embedchain/embedchain/loaders/gmail.py b/embedchain/embedchain/loaders/gmail.py deleted file mode 100644 index ec62a34b3..000000000 --- a/embedchain/embedchain/loaders/gmail.py +++ /dev/null @@ -1,144 +0,0 @@ -import base64 -import hashlib -import logging -import os -from email import message_from_bytes -from email.utils import parsedate_to_datetime -from textwrap import dedent -from typing import Optional - -from bs4 import BeautifulSoup - -try: - from google.auth.transport.requests import Request - from google.oauth2.credentials import Credentials - from google_auth_oauthlib.flow import InstalledAppFlow - from googleapiclient.discovery import build -except ImportError: - raise ImportError( - 'Gmail requires extra dependencies. Install with `pip install --upgrade "embedchain[gmail]"`' - ) from None - -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import clean_string - -logger = logging.getLogger(__name__) - - -class GmailReader: - SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"] - - def __init__(self, query: str, service=None, results_per_page: int = 10): - self.query = query - self.service = service or self._initialize_service() - self.results_per_page = results_per_page - - @staticmethod - def _initialize_service(): - credentials = GmailReader._get_credentials() - return build("gmail", "v1", credentials=credentials) - - @staticmethod - def _get_credentials(): - if not os.path.exists("credentials.json"): - raise FileNotFoundError("Missing 'credentials.json'. Download it from your Google Developer account.") - - creds = ( - Credentials.from_authorized_user_file("token.json", GmailReader.SCOPES) - if os.path.exists("token.json") - else None - ) - - if not creds or not creds.valid: - if creds and creds.expired and creds.refresh_token: - creds.refresh(Request()) - else: - flow = InstalledAppFlow.from_client_secrets_file("credentials.json", GmailReader.SCOPES) - creds = flow.run_local_server(port=8080) - with open("token.json", "w") as token: - token.write(creds.to_json()) - return creds - - def load_emails(self) -> list[dict]: - response = self.service.users().messages().list(userId="me", q=self.query).execute() - messages = response.get("messages", []) - - return [self._parse_email(self._get_email(message["id"])) for message in messages] - - def _get_email(self, message_id: str): - raw_message = self.service.users().messages().get(userId="me", id=message_id, format="raw").execute() - return base64.urlsafe_b64decode(raw_message["raw"]) - - def _parse_email(self, raw_email) -> dict: - mime_msg = message_from_bytes(raw_email) - return { - "subject": self._get_header(mime_msg, "Subject"), - "from": self._get_header(mime_msg, "From"), - "to": self._get_header(mime_msg, "To"), - "date": self._format_date(mime_msg), - "body": self._get_body(mime_msg), - } - - @staticmethod - def _get_header(mime_msg, header_name: str) -> str: - return mime_msg.get(header_name, "") - - @staticmethod - def _format_date(mime_msg) -> Optional[str]: - date_header = GmailReader._get_header(mime_msg, "Date") - return parsedate_to_datetime(date_header).isoformat() if date_header else None - - @staticmethod - def _get_body(mime_msg) -> str: - def decode_payload(part): - charset = part.get_content_charset() or "utf-8" - try: - return part.get_payload(decode=True).decode(charset) - except UnicodeDecodeError: - return part.get_payload(decode=True).decode(charset, errors="replace") - - if mime_msg.is_multipart(): - for part in mime_msg.walk(): - ctype = part.get_content_type() - cdispo = str(part.get("Content-Disposition")) - - if ctype == "text/plain" and "attachment" not in cdispo: - return decode_payload(part) - elif ctype == "text/html": - return decode_payload(part) - else: - return decode_payload(mime_msg) - - return "" - - -class GmailLoader(BaseLoader): - def load_data(self, query: str): - reader = GmailReader(query=query) - emails = reader.load_emails() - logger.info(f"Gmail Loader: {len(emails)} emails found for query '{query}'") - - data = [] - for email in emails: - content = self._process_email(email) - data.append({"content": content, "meta_data": email}) - - return {"doc_id": self._generate_doc_id(query, data), "data": data} - - @staticmethod - def _process_email(email: dict) -> str: - content = BeautifulSoup(email["body"], "html.parser").get_text() - content = clean_string(content) - return dedent( - f""" - Email from '{email['from']}' to '{email['to']}' - Subject: {email['subject']} - Date: {email['date']} - Content: {content} - """ - ) - - @staticmethod - def _generate_doc_id(query: str, data: list[dict]) -> str: - content_strings = [email["content"] for email in data] - return hashlib.sha256((query + ", ".join(content_strings)).encode()).hexdigest() diff --git a/embedchain/embedchain/loaders/google_drive.py b/embedchain/embedchain/loaders/google_drive.py deleted file mode 100644 index d24046242..000000000 --- a/embedchain/embedchain/loaders/google_drive.py +++ /dev/null @@ -1,62 +0,0 @@ -import hashlib -import re - -try: - from googleapiclient.errors import HttpError -except ImportError: - raise ImportError( - "Google Drive requires extra dependencies. Install with `pip install embedchain[googledrive]`" - ) from None - -from langchain_community.document_loaders import GoogleDriveLoader as Loader - -try: - import unstructured # noqa: F401 - from langchain_community.document_loaders import UnstructuredFileIOLoader -except ImportError: - raise ImportError( - 'Unstructured file requires extra dependencies. Install with `pip install "unstructured[local-inference, all-docs]"`' # noqa: E501 - ) from None - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader - - -@register_deserializable -class GoogleDriveLoader(BaseLoader): - @staticmethod - def _get_drive_id_from_url(url: str): - regex = r"^https:\/\/drive\.google\.com\/drive\/(?:u\/\d+\/)folders\/([a-zA-Z0-9_-]+)$" - if re.match(regex, url): - return url.split("/")[-1] - raise ValueError( - f"The url provided {url} does not match a google drive folder url. Example drive url: " - f"https://drive.google.com/drive/u/0/folders/xxxx" - ) - - def load_data(self, url: str): - """Load data from a Google drive folder.""" - folder_id: str = self._get_drive_id_from_url(url) - - try: - loader = Loader( - folder_id=folder_id, - recursive=True, - file_loader_cls=UnstructuredFileIOLoader, - ) - - data = [] - all_content = [] - - docs = loader.load() - for doc in docs: - all_content.append(doc.page_content) - # renames source to url for later use. - doc.metadata["url"] = doc.metadata.pop("source") - data.append({"content": doc.page_content, "meta_data": doc.metadata}) - - doc_id = hashlib.sha256((" ".join(all_content) + url).encode()).hexdigest() - return {"doc_id": doc_id, "data": data} - - except HttpError: - raise FileNotFoundError("Unable to locate folder or files, check provided drive URL and try again") diff --git a/embedchain/embedchain/loaders/image.py b/embedchain/embedchain/loaders/image.py deleted file mode 100644 index 18b31873b..000000000 --- a/embedchain/embedchain/loaders/image.py +++ /dev/null @@ -1,50 +0,0 @@ -import base64 -import hashlib -import os -from pathlib import Path - -from openai import OpenAI - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader - -DESCRIBE_IMAGE_PROMPT = "Describe the image:" - - -@register_deserializable -class ImageLoader(BaseLoader): - def __init__(self, max_tokens: int = 500, api_key: str = None, prompt: str = None): - super().__init__() - self.custom_prompt = prompt or DESCRIBE_IMAGE_PROMPT - self.max_tokens = max_tokens - self.api_key = api_key or os.environ["OPENAI_API_KEY"] - self.client = OpenAI(api_key=self.api_key) - - @staticmethod - def _encode_image(image_path: str): - with open(image_path, "rb") as image_file: - return base64.b64encode(image_file.read()).decode("utf-8") - - def _create_completion_request(self, content: str): - return self.client.chat.completions.create( - model="gpt-4o", messages=[{"role": "user", "content": content}], max_tokens=self.max_tokens - ) - - def _process_url(self, url: str): - if url.startswith("http"): - return [{"type": "text", "text": self.custom_prompt}, {"type": "image_url", "image_url": {"url": url}}] - elif Path(url).is_file(): - extension = Path(url).suffix.lstrip(".") - encoded_image = self._encode_image(url) - image_data = f"data:image/{extension};base64,{encoded_image}" - return [{"type": "text", "text": self.custom_prompt}, {"type": "image", "image_url": {"url": image_data}}] - else: - raise ValueError(f"Invalid URL or file path: {url}") - - def load_data(self, url: str): - content = self._process_url(url) - response = self._create_completion_request(content) - content = response.choices[0].message.content - - doc_id = hashlib.sha256((content + url).encode()).hexdigest() - return {"doc_id": doc_id, "data": [{"content": content, "meta_data": {"url": url, "type": "image"}}]} diff --git a/embedchain/embedchain/loaders/json.py b/embedchain/embedchain/loaders/json.py deleted file mode 100644 index 587aa1492..000000000 --- a/embedchain/embedchain/loaders/json.py +++ /dev/null @@ -1,93 +0,0 @@ -import hashlib -import json -import os -import re -from typing import Union - -import requests - -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import clean_string, is_valid_json_string - - -class JSONReader: - def __init__(self) -> None: - """Initialize the JSONReader.""" - pass - - @staticmethod - def load_data(json_data: Union[dict, str]) -> list[str]: - """Load data from a JSON structure. - - Args: - json_data (Union[dict, str]): The JSON data to load. - - Returns: - list[str]: A list of strings representing the leaf nodes of the JSON. - """ - if isinstance(json_data, str): - json_data = json.loads(json_data) - else: - json_data = json_data - - json_output = json.dumps(json_data, indent=0) - lines = json_output.split("\n") - useful_lines = [line for line in lines if not re.match(r"^[{}\[\],]*$", line)] - return ["\n".join(useful_lines)] - - -VALID_URL_PATTERN = ( - "^https?://(?:www\.)?(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[a-zA-Z0-9.-]+)(?::\d+)?/(?:[^/\s]+/)*[^/\s]+\.json$" -) - - -class JSONLoader(BaseLoader): - @staticmethod - def _check_content(content): - if not isinstance(content, str): - raise ValueError( - "Invaid content input. \ - If you want to upload (list, dict, etc.), do \ - `json.dump(data, indent=0)` and add the stringified JSON. \ - Check - `https://docs.embedchain.ai/data-sources/json`" - ) - - @staticmethod - def load_data(content): - """Load a json file. Each data point is a key value pair.""" - - JSONLoader._check_content(content) - loader = JSONReader() - - data = [] - data_content = [] - - content_url_str = content - - if os.path.isfile(content): - with open(content, "r", encoding="utf-8") as json_file: - json_data = json.load(json_file) - elif re.match(VALID_URL_PATTERN, content): - response = requests.get(content) - if response.status_code == 200: - json_data = response.json() - else: - raise ValueError( - f"Loading data from the given url: {content} failed. \ - Make sure the url is working." - ) - elif is_valid_json_string(content): - json_data = content - content_url_str = hashlib.sha256((content).encode("utf-8")).hexdigest() - else: - raise ValueError(f"Invalid content to load json data from: {content}") - - docs = loader.load_data(json_data) - for doc in docs: - text = doc if isinstance(doc, str) else doc["text"] - doc_content = clean_string(text) - data.append({"content": doc_content, "meta_data": {"url": content_url_str}}) - data_content.append(doc_content) - - doc_id = hashlib.sha256((content_url_str + ", ".join(data_content)).encode()).hexdigest() - return {"doc_id": doc_id, "data": data} diff --git a/embedchain/embedchain/loaders/local_qna_pair.py b/embedchain/embedchain/loaders/local_qna_pair.py deleted file mode 100644 index c93adfdae..000000000 --- a/embedchain/embedchain/loaders/local_qna_pair.py +++ /dev/null @@ -1,24 +0,0 @@ -import hashlib - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader - - -@register_deserializable -class LocalQnaPairLoader(BaseLoader): - def load_data(self, content): - """Load data from a local QnA pair.""" - question, answer = content - content = f"Q: {question}\nA: {answer}" - url = "local" - metadata = {"url": url, "question": question} - doc_id = hashlib.sha256((content + url).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": [ - { - "content": content, - "meta_data": metadata, - } - ], - } diff --git a/embedchain/embedchain/loaders/local_text.py b/embedchain/embedchain/loaders/local_text.py deleted file mode 100644 index 98a98cd67..000000000 --- a/embedchain/embedchain/loaders/local_text.py +++ /dev/null @@ -1,24 +0,0 @@ -import hashlib - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader - - -@register_deserializable -class LocalTextLoader(BaseLoader): - def load_data(self, content): - """Load data from a local text file.""" - url = "local" - metadata = { - "url": url, - } - doc_id = hashlib.sha256((content + url).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": [ - { - "content": content, - "meta_data": metadata, - } - ], - } diff --git a/embedchain/embedchain/loaders/mdx.py b/embedchain/embedchain/loaders/mdx.py deleted file mode 100644 index 42b9b7fee..000000000 --- a/embedchain/embedchain/loaders/mdx.py +++ /dev/null @@ -1,25 +0,0 @@ -import hashlib - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader - - -@register_deserializable -class MdxLoader(BaseLoader): - def load_data(self, url): - """Load data from a mdx file.""" - with open(url, "r", encoding="utf-8") as infile: - content = infile.read() - metadata = { - "url": url, - } - doc_id = hashlib.sha256((content + url).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": [ - { - "content": content, - "meta_data": metadata, - } - ], - } diff --git a/embedchain/embedchain/loaders/mysql.py b/embedchain/embedchain/loaders/mysql.py deleted file mode 100644 index fd5b38ac2..000000000 --- a/embedchain/embedchain/loaders/mysql.py +++ /dev/null @@ -1,67 +0,0 @@ -import hashlib -import logging -from typing import Any, Optional - -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import clean_string - -logger = logging.getLogger(__name__) - - -class MySQLLoader(BaseLoader): - def __init__(self, config: Optional[dict[str, Any]]): - super().__init__() - if not config: - raise ValueError( - f"Invalid sql config: {config}.", - "Provide the correct config, refer `https://docs.embedchain.ai/data-sources/mysql`.", - ) - - self.config = config - self.connection = None - self.cursor = None - self._setup_loader(config=config) - - def _setup_loader(self, config: dict[str, Any]): - try: - import mysql.connector as sqlconnector - except ImportError as e: - raise ImportError( - "Unable to import required packages for MySQL loader. Run `pip install --upgrade 'embedchain[mysql]'`." # noqa: E501 - ) from e - - try: - self.connection = sqlconnector.connection.MySQLConnection(**config) - self.cursor = self.connection.cursor() - except (sqlconnector.Error, IOError) as err: - logger.info(f"Connection failed: {err}") - raise ValueError( - f"Unable to connect with the given config: {config}.", - "Please provide the correct configuration to load data from you MySQL DB. \ - Refer `https://docs.embedchain.ai/data-sources/mysql`.", - ) - - @staticmethod - def _check_query(query): - if not isinstance(query, str): - raise ValueError( - f"Invalid mysql query: {query}", - "Provide the valid query to add from mysql, \ - make sure you are following `https://docs.embedchain.ai/data-sources/mysql`", - ) - - def load_data(self, query): - self._check_query(query=query) - data = [] - data_content = [] - self.cursor.execute(query) - rows = self.cursor.fetchall() - for row in rows: - doc_content = clean_string(str(row)) - data.append({"content": doc_content, "meta_data": {"url": query}}) - data_content.append(doc_content) - doc_id = hashlib.sha256((query + ", ".join(data_content)).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": data, - } diff --git a/embedchain/embedchain/loaders/notion.py b/embedchain/embedchain/loaders/notion.py deleted file mode 100644 index 2a3363818..000000000 --- a/embedchain/embedchain/loaders/notion.py +++ /dev/null @@ -1,121 +0,0 @@ -import hashlib -import logging -import os -from typing import Any, Optional - -import requests - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import clean_string - -logger = logging.getLogger(__name__) - - -class NotionDocument: - """ - A simple Document class to hold the text and additional information of a page. - """ - - def __init__(self, text: str, extra_info: dict[str, Any]): - self.text = text - self.extra_info = extra_info - - -class NotionPageLoader: - """ - Notion Page Loader. - Reads a set of Notion pages. - """ - - BLOCK_CHILD_URL_TMPL = "https://api.notion.com/v1/blocks/{block_id}/children" - - def __init__(self, integration_token: Optional[str] = None) -> None: - """Initialize with Notion integration token.""" - if integration_token is None: - integration_token = os.getenv("NOTION_INTEGRATION_TOKEN") - if integration_token is None: - raise ValueError( - "Must specify `integration_token` or set environment " "variable `NOTION_INTEGRATION_TOKEN`." - ) - self.token = integration_token - self.headers = { - "Authorization": "Bearer " + self.token, - "Content-Type": "application/json", - "Notion-Version": "2022-06-28", - } - - def _read_block(self, block_id: str, num_tabs: int = 0) -> str: - """Read a block from Notion.""" - done = False - result_lines_arr = [] - cur_block_id = block_id - while not done: - block_url = self.BLOCK_CHILD_URL_TMPL.format(block_id=cur_block_id) - res = requests.get(block_url, headers=self.headers) - data = res.json() - - for result in data["results"]: - result_type = result["type"] - result_obj = result[result_type] - - cur_result_text_arr = [] - if "rich_text" in result_obj: - for rich_text in result_obj["rich_text"]: - if "text" in rich_text: - text = rich_text["text"]["content"] - prefix = "\t" * num_tabs - cur_result_text_arr.append(prefix + text) - - result_block_id = result["id"] - has_children = result["has_children"] - if has_children: - children_text = self._read_block(result_block_id, num_tabs=num_tabs + 1) - cur_result_text_arr.append(children_text) - - cur_result_text = "\n".join(cur_result_text_arr) - result_lines_arr.append(cur_result_text) - - if data["next_cursor"] is None: - done = True - else: - cur_block_id = data["next_cursor"] - - result_lines = "\n".join(result_lines_arr) - return result_lines - - def load_data(self, page_ids: list[str]) -> list[NotionDocument]: - """Load data from the given list of page IDs.""" - docs = [] - for page_id in page_ids: - page_text = self._read_block(page_id) - docs.append(NotionDocument(text=page_text, extra_info={"page_id": page_id})) - return docs - - -@register_deserializable -class NotionLoader(BaseLoader): - def load_data(self, source): - """Load data from a Notion URL.""" - - id = source[-32:] - formatted_id = f"{id[:8]}-{id[8:12]}-{id[12:16]}-{id[16:20]}-{id[20:]}" - logger.debug(f"Extracted notion page id as: {formatted_id}") - - integration_token = os.getenv("NOTION_INTEGRATION_TOKEN") - reader = NotionPageLoader(integration_token=integration_token) - documents = reader.load_data(page_ids=[formatted_id]) - - raw_text = documents[0].text - - text = clean_string(raw_text) - doc_id = hashlib.sha256((text + source).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": [ - { - "content": text, - "meta_data": {"url": f"notion-{formatted_id}"}, - } - ], - } diff --git a/embedchain/embedchain/loaders/openapi.py b/embedchain/embedchain/loaders/openapi.py deleted file mode 100644 index 18983b9a3..000000000 --- a/embedchain/embedchain/loaders/openapi.py +++ /dev/null @@ -1,42 +0,0 @@ -import hashlib -from io import StringIO -from urllib.parse import urlparse - -import requests -import yaml - -from embedchain.loaders.base_loader import BaseLoader - - -class OpenAPILoader(BaseLoader): - @staticmethod - def _get_file_content(content): - url = urlparse(content) - if all([url.scheme, url.netloc]) and url.scheme not in ["file", "http", "https"]: - raise ValueError("Not a valid URL.") - - if url.scheme in ["http", "https"]: - response = requests.get(content) - response.raise_for_status() - return StringIO(response.text) - elif url.scheme == "file": - path = url.path - return open(path) - else: - return open(content) - - @staticmethod - def load_data(content): - """Load yaml file of openapi. Each pair is a document.""" - data = [] - file_path = content - data_content = [] - with OpenAPILoader._get_file_content(content=content) as file: - yaml_data = yaml.load(file, Loader=yaml.SafeLoader) - for i, (key, value) in enumerate(yaml_data.items()): - string_data = f"{key}: {value}" - metadata = {"url": file_path, "row": i + 1} - data.append({"content": string_data, "meta_data": metadata}) - data_content.append(string_data) - doc_id = hashlib.sha256((content + ", ".join(data_content)).encode()).hexdigest() - return {"doc_id": doc_id, "data": data} diff --git a/embedchain/embedchain/loaders/pdf_file.py b/embedchain/embedchain/loaders/pdf_file.py deleted file mode 100644 index a7f6d5540..000000000 --- a/embedchain/embedchain/loaders/pdf_file.py +++ /dev/null @@ -1,39 +0,0 @@ -import hashlib - -from langchain_community.document_loaders import PyPDFLoader - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import clean_string - - -@register_deserializable -class PdfFileLoader(BaseLoader): - def load_data(self, url): - """Load data from a PDF file.""" - headers = { - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", # noqa:E501 - } - loader = PyPDFLoader(url, headers=headers) - data = [] - all_content = [] - pages = loader.load_and_split() - if not len(pages): - raise ValueError("No data found") - for page in pages: - content = page.page_content - content = clean_string(content) - metadata = page.metadata - metadata["url"] = url - data.append( - { - "content": content, - "meta_data": metadata, - } - ) - all_content.append(content) - doc_id = hashlib.sha256((" ".join(all_content) + url).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": data, - } diff --git a/embedchain/embedchain/loaders/postgres.py b/embedchain/embedchain/loaders/postgres.py deleted file mode 100644 index 2ef396f9d..000000000 --- a/embedchain/embedchain/loaders/postgres.py +++ /dev/null @@ -1,73 +0,0 @@ -import hashlib -import logging -from typing import Any, Optional - -from embedchain.loaders.base_loader import BaseLoader - -logger = logging.getLogger(__name__) - - -class PostgresLoader(BaseLoader): - def __init__(self, config: Optional[dict[str, Any]] = None): - super().__init__() - if not config: - raise ValueError(f"Must provide the valid config. Received: {config}") - - self.connection = None - self.cursor = None - self._setup_loader(config=config) - - def _setup_loader(self, config: dict[str, Any]): - try: - import psycopg - except ImportError as e: - raise ImportError( - "Unable to import required packages. \ - Run `pip install --upgrade 'embedchain[postgres]'`" - ) from e - - if "url" in config: - config_info = config.get("url") - else: - conn_params = [] - for key, value in config.items(): - conn_params.append(f"{key}={value}") - config_info = " ".join(conn_params) - - logger.info(f"Connecting to postrgres sql: {config_info}") - self.connection = psycopg.connect(conninfo=config_info) - self.cursor = self.connection.cursor() - - @staticmethod - def _check_query(query): - if not isinstance(query, str): - raise ValueError( - f"Invalid postgres query: {query}. Provide the valid source to add from postgres, make sure you are following `https://docs.embedchain.ai/data-sources/postgres`", # noqa:E501 - ) - - def load_data(self, query): - self._check_query(query) - try: - data = [] - data_content = [] - self.cursor.execute(query) - results = self.cursor.fetchall() - for result in results: - doc_content = str(result) - data.append({"content": doc_content, "meta_data": {"url": query}}) - data_content.append(doc_content) - doc_id = hashlib.sha256((query + ", ".join(data_content)).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": data, - } - except Exception as e: - raise ValueError(f"Failed to load data using query={query} with: {e}") - - def close_connection(self): - if self.cursor: - self.cursor.close() - self.cursor = None - if self.connection: - self.connection.close() - self.connection = None diff --git a/embedchain/embedchain/loaders/rss_feed.py b/embedchain/embedchain/loaders/rss_feed.py deleted file mode 100644 index bc17c68bc..000000000 --- a/embedchain/embedchain/loaders/rss_feed.py +++ /dev/null @@ -1,54 +0,0 @@ -import hashlib - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader - - -@register_deserializable -class RSSFeedLoader(BaseLoader): - """Loader for RSS Feed.""" - - def load_data(self, url): - """Load data from a rss feed.""" - output = self.get_rss_content(url) - doc_id = hashlib.sha256((str(output) + url).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": output, - } - - @staticmethod - def serialize_metadata(metadata): - for key, value in metadata.items(): - if not isinstance(value, (str, int, float, bool)): - metadata[key] = str(value) - - return metadata - - @staticmethod - def get_rss_content(url: str): - try: - from langchain_community.document_loaders import ( - RSSFeedLoader as LangchainRSSFeedLoader, - ) - except ImportError: - raise ImportError( - """RSSFeedLoader file requires extra dependencies. - Install with `pip install feedparser==6.0.10 newspaper3k==0.2.8 listparser==0.19`""" - ) from None - - output = [] - loader = LangchainRSSFeedLoader(urls=[url]) - data = loader.load() - - for entry in data: - metadata = RSSFeedLoader.serialize_metadata(entry.metadata) - metadata.update({"url": url}) - output.append( - { - "content": entry.page_content, - "meta_data": metadata, - } - ) - - return output diff --git a/embedchain/embedchain/loaders/sitemap.py b/embedchain/embedchain/loaders/sitemap.py deleted file mode 100644 index 098ca06df..000000000 --- a/embedchain/embedchain/loaders/sitemap.py +++ /dev/null @@ -1,79 +0,0 @@ -import concurrent.futures -import hashlib -import logging -import os -from urllib.parse import urlparse - -import requests -from tqdm import tqdm - -try: - from bs4 import BeautifulSoup - from bs4.builder import ParserRejectedMarkup -except ImportError: - raise ImportError( - "Sitemap requires extra dependencies. Install with `pip install beautifulsoup4==4.12.3`" - ) from None - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader -from embedchain.loaders.web_page import WebPageLoader - -logger = logging.getLogger(__name__) - - -@register_deserializable -class SitemapLoader(BaseLoader): - """ - This method takes a sitemap URL or local file path as input and retrieves - all the URLs to use the WebPageLoader to load content - of each page. - """ - - def load_data(self, sitemap_source): - output = [] - web_page_loader = WebPageLoader() - headers = { - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", # noqa:E501 - } - - if urlparse(sitemap_source).scheme in ("http", "https"): - try: - response = requests.get(sitemap_source, headers=headers) - response.raise_for_status() - soup = BeautifulSoup(response.text, "xml") - except requests.RequestException as e: - logger.error(f"Error fetching sitemap from URL: {e}") - return - elif os.path.isfile(sitemap_source): - with open(sitemap_source, "r") as file: - soup = BeautifulSoup(file, "xml") - else: - raise ValueError("Invalid sitemap source. Please provide a valid URL or local file path.") - - links = [link.text for link in soup.find_all("loc") if link.parent.name == "url"] - if len(links) == 0: - links = [link.text for link in soup.find_all("loc")] - - doc_id = hashlib.sha256((" ".join(links) + sitemap_source).encode()).hexdigest() - - def load_web_page(link): - try: - loader_data = web_page_loader.load_data(link) - return loader_data.get("data") - except ParserRejectedMarkup as e: - logger.error(f"Failed to parse {link}: {e}") - return None - - with concurrent.futures.ThreadPoolExecutor() as executor: - future_to_link = {executor.submit(load_web_page, link): link for link in links} - for future in tqdm(concurrent.futures.as_completed(future_to_link), total=len(links), desc="Loading pages"): - link = future_to_link[future] - try: - data = future.result() - if data: - output.extend(data) - except Exception as e: - logger.error(f"Error loading page {link}: {e}") - - return {"doc_id": doc_id, "data": output} diff --git a/embedchain/embedchain/loaders/slack.py b/embedchain/embedchain/loaders/slack.py deleted file mode 100644 index 6fb6e9db8..000000000 --- a/embedchain/embedchain/loaders/slack.py +++ /dev/null @@ -1,115 +0,0 @@ -import hashlib -import logging -import os -import ssl -from typing import Any, Optional - -import certifi - -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import clean_string - -SLACK_API_BASE_URL = "https://www.slack.com/api/" - -logger = logging.getLogger(__name__) - - -class SlackLoader(BaseLoader): - def __init__(self, config: Optional[dict[str, Any]] = None): - super().__init__() - - self.config = config if config else {} - - if "base_url" not in self.config: - self.config["base_url"] = SLACK_API_BASE_URL - - self.client = None - self._setup_loader(self.config) - - def _setup_loader(self, config: dict[str, Any]): - try: - from slack_sdk import WebClient - except ImportError as e: - raise ImportError( - "Slack loader requires extra dependencies. \ - Install with `pip install --upgrade embedchain[slack]`" - ) from e - - if os.getenv("SLACK_USER_TOKEN") is None: - raise ValueError( - "SLACK_USER_TOKEN environment variables not provided. Check `https://docs.embedchain.ai/data-sources/slack` to learn more." # noqa:E501 - ) - - logger.info(f"Creating Slack Loader with config: {config}") - # get slack client config params - slack_bot_token = os.getenv("SLACK_USER_TOKEN") - ssl_cert = ssl.create_default_context(cafile=certifi.where()) - base_url = config.get("base_url", SLACK_API_BASE_URL) - headers = config.get("headers") - # for Org-Wide App - team_id = config.get("team_id") - - self.client = WebClient( - token=slack_bot_token, - base_url=base_url, - ssl=ssl_cert, - headers=headers, - team_id=team_id, - ) - logger.info("Slack Loader setup successful!") - - @staticmethod - def _check_query(query): - if not isinstance(query, str): - raise ValueError( - f"Invalid query passed to Slack loader, found: {query}. Check `https://docs.embedchain.ai/data-sources/slack` to learn more." # noqa:E501 - ) - - def load_data(self, query): - self._check_query(query) - try: - data = [] - data_content = [] - - logger.info(f"Searching slack conversations for query: {query}") - results = self.client.search_messages( - query=query, - sort="timestamp", - sort_dir="desc", - count=self.config.get("count", 100), - ) - - messages = results.get("messages") - num_message = len(messages) - logger.info(f"Found {num_message} messages for query: {query}") - - matches = messages.get("matches", []) - for message in matches: - url = message.get("permalink") - text = message.get("text") - content = clean_string(text) - - message_meta_data_keys = ["iid", "team", "ts", "type", "user", "username"] - metadata = {} - for key in message.keys(): - if key in message_meta_data_keys: - metadata[key] = message.get(key) - metadata.update({"url": url}) - - data.append( - { - "content": content, - "meta_data": metadata, - } - ) - data_content.append(content) - doc_id = hashlib.md5((query + ", ".join(data_content)).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": data, - } - except Exception as e: - logger.warning(f"Error in loading slack data: {e}") - raise ValueError( - f"Error in loading slack data: {e}. Check `https://docs.embedchain.ai/data-sources/slack` to learn more." # noqa:E501 - ) from e diff --git a/embedchain/embedchain/loaders/substack.py b/embedchain/embedchain/loaders/substack.py deleted file mode 100644 index 15c08a5bb..000000000 --- a/embedchain/embedchain/loaders/substack.py +++ /dev/null @@ -1,107 +0,0 @@ -import hashlib -import logging -import time -from xml.etree import ElementTree - -import requests - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import is_readable - -logger = logging.getLogger(__name__) - - -@register_deserializable -class SubstackLoader(BaseLoader): - """ - This loader is used to load data from Substack URLs. - """ - - def load_data(self, url: str): - try: - from bs4 import BeautifulSoup - from bs4.builder import ParserRejectedMarkup - except ImportError: - raise ImportError( - "Substack requires extra dependencies. Install with `pip install beautifulsoup4==4.12.3`" - ) from None - - if not url.endswith("sitemap.xml"): - url = url + "/sitemap.xml" - - output = [] - response = requests.get(url) - - try: - response.raise_for_status() - except requests.exceptions.HTTPError as e: - raise ValueError( - f""" - Failed to load {url}: {e}. Please use the root substack URL. For example, https://example.substack.com - """ - ) - - try: - ElementTree.fromstring(response.content) - except ElementTree.ParseError: - raise ValueError( - f""" - Failed to parse {url}. Please use the root substack URL. For example, https://example.substack.com - """ - ) - - soup = BeautifulSoup(response.text, "xml") - links = [link.text for link in soup.find_all("loc") if link.parent.name == "url" and "/p/" in link.text] - if len(links) == 0: - links = [link.text for link in soup.find_all("loc") if "/p/" in link.text] - - doc_id = hashlib.sha256((" ".join(links) + url).encode()).hexdigest() - - def serialize_response(soup: BeautifulSoup): - data = {} - - h1_els = soup.find_all("h1") - if h1_els is not None and len(h1_els) > 0: - data["title"] = h1_els[1].text - - description_el = soup.find("meta", {"name": "description"}) - if description_el is not None: - data["description"] = description_el["content"] - - content_el = soup.find("div", {"class": "available-content"}) - if content_el is not None: - data["content"] = content_el.text - - like_btn = soup.find("div", {"class": "like-button-container"}) - if like_btn is not None: - no_of_likes_div = like_btn.find("div", {"class": "label"}) - if no_of_likes_div is not None: - data["no_of_likes"] = no_of_likes_div.text - - return data - - def load_link(link: str): - try: - substack_data = requests.get(link) - substack_data.raise_for_status() - - soup = BeautifulSoup(substack_data.text, "html.parser") - data = serialize_response(soup) - data = str(data) - if is_readable(data): - return data - else: - logger.warning(f"Page is not readable (too many invalid characters): {link}") - except ParserRejectedMarkup as e: - logger.error(f"Failed to parse {link}: {e}") - return None - - for link in links: - data = load_link(link) - if data: - output.append({"content": data, "meta_data": {"url": link}}) - # TODO: allow users to configure this - time.sleep(1.0) # added to avoid rate limiting - - return {"doc_id": doc_id, "data": output} diff --git a/embedchain/embedchain/loaders/text_file.py b/embedchain/embedchain/loaders/text_file.py deleted file mode 100644 index bc7fb4b09..000000000 --- a/embedchain/embedchain/loaders/text_file.py +++ /dev/null @@ -1,30 +0,0 @@ -import hashlib -import os - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader - - -@register_deserializable -class TextFileLoader(BaseLoader): - def load_data(self, url: str): - """Load data from a text file located at a local path.""" - if not os.path.exists(url): - raise FileNotFoundError(f"The file at {url} does not exist.") - - with open(url, "r", encoding="utf-8") as file: - content = file.read() - - doc_id = hashlib.sha256((content + url).encode()).hexdigest() - - metadata = {"url": url, "file_size": os.path.getsize(url), "file_type": url.split(".")[-1]} - - return { - "doc_id": doc_id, - "data": [ - { - "content": content, - "meta_data": metadata, - } - ], - } diff --git a/embedchain/embedchain/loaders/unstructured_file.py b/embedchain/embedchain/loaders/unstructured_file.py deleted file mode 100644 index 856ac888b..000000000 --- a/embedchain/embedchain/loaders/unstructured_file.py +++ /dev/null @@ -1,42 +0,0 @@ -import hashlib - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import clean_string - - -@register_deserializable -class UnstructuredLoader(BaseLoader): - def load_data(self, url): - """Load data from an Unstructured file.""" - try: - import unstructured # noqa: F401 - from langchain_community.document_loaders import UnstructuredFileLoader - except ImportError: - raise ImportError( - 'Unstructured file requires extra dependencies. Install with `pip install "unstructured[local-inference, all-docs]"`' # noqa: E501 - ) from None - - loader = UnstructuredFileLoader(url) - data = [] - all_content = [] - pages = loader.load_and_split() - if not len(pages): - raise ValueError("No data found") - for page in pages: - content = page.page_content - content = clean_string(content) - metadata = page.metadata - metadata["url"] = url - data.append( - { - "content": content, - "meta_data": metadata, - } - ) - all_content.append(content) - doc_id = hashlib.sha256((" ".join(all_content) + url).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": data, - } diff --git a/embedchain/embedchain/loaders/web_page.py b/embedchain/embedchain/loaders/web_page.py deleted file mode 100644 index 848bc2038..000000000 --- a/embedchain/embedchain/loaders/web_page.py +++ /dev/null @@ -1,126 +0,0 @@ -import hashlib -import logging -from typing import Any, Optional - -import requests - -try: - from bs4 import BeautifulSoup -except ImportError: - raise ImportError( - "Webpage requires extra dependencies. Install with `pip install beautifulsoup4==4.12.3`" - ) from None - -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import clean_string - -logger = logging.getLogger(__name__) - - -@register_deserializable -class WebPageLoader(BaseLoader): - # Shared session for all instances - _session = requests.Session() - - def load_data(self, url, **kwargs: Optional[dict[str, Any]]): - """Load data from a web page using a shared requests' session.""" - all_references = False - for key, value in kwargs.items(): - if key == "all_references": - all_references = kwargs["all_references"] - headers = { - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", # noqa:E501 - } - response = self._session.get(url, headers=headers, timeout=30) - response.raise_for_status() - data = response.content - reference_links = self.fetch_reference_links(response) - if all_references: - for i in reference_links: - try: - response = self._session.get(i, headers=headers, timeout=30) - response.raise_for_status() - data += response.content - except Exception as e: - logging.error(f"Failed to add URL {url}: {e}") - continue - - content = self._get_clean_content(data, url) - - metadata = {"url": url} - - doc_id = hashlib.sha256((content + url).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": [ - { - "content": content, - "meta_data": metadata, - } - ], - } - - @staticmethod - def _get_clean_content(html, url) -> str: - soup = BeautifulSoup(html, "html.parser") - original_size = len(str(soup.get_text())) - - tags_to_exclude = [ - "nav", - "aside", - "form", - "header", - "noscript", - "svg", - "canvas", - "footer", - "script", - "style", - ] - for tag in soup(tags_to_exclude): - tag.decompose() - - ids_to_exclude = ["sidebar", "main-navigation", "menu-main-menu"] - for id_ in ids_to_exclude: - tags = soup.find_all(id=id_) - for tag in tags: - tag.decompose() - - classes_to_exclude = [ - "elementor-location-header", - "navbar-header", - "nav", - "header-sidebar-wrapper", - "blog-sidebar-wrapper", - "related-posts", - ] - for class_name in classes_to_exclude: - tags = soup.find_all(class_=class_name) - for tag in tags: - tag.decompose() - - content = soup.get_text() - content = clean_string(content) - - cleaned_size = len(content) - if original_size != 0: - logger.info( - f"[{url}] Cleaned page size: {cleaned_size} characters, down from {original_size} (shrunk: {original_size-cleaned_size} chars, {round((1-(cleaned_size/original_size)) * 100, 2)}%)" # noqa:E501 - ) - - return content - - @classmethod - def close_session(cls): - cls._session.close() - - def fetch_reference_links(self, response): - if response.status_code == 200: - soup = BeautifulSoup(response.content, "html.parser") - a_tags = soup.find_all("a", href=True) - reference_links = [a["href"] for a in a_tags if a["href"].startswith("http")] - return reference_links - else: - print(f"Failed to retrieve the page. Status code: {response.status_code}") - return [] diff --git a/embedchain/embedchain/loaders/xml.py b/embedchain/embedchain/loaders/xml.py deleted file mode 100644 index 0c2c8c748..000000000 --- a/embedchain/embedchain/loaders/xml.py +++ /dev/null @@ -1,31 +0,0 @@ -import hashlib - -try: - import unstructured # noqa: F401 - from langchain_community.document_loaders import UnstructuredXMLLoader -except ImportError: - raise ImportError( - 'XML file requires extra dependencies. Install with `pip install "unstructured[local-inference, all-docs]"`' - ) from None -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import clean_string - - -@register_deserializable -class XmlLoader(BaseLoader): - def load_data(self, xml_url): - """Load data from a XML file.""" - loader = UnstructuredXMLLoader(xml_url) - data = loader.load() - content = data[0].page_content - content = clean_string(content) - metadata = data[0].metadata - metadata["url"] = metadata["source"] - del metadata["source"] - output = [{"content": content, "meta_data": metadata}] - doc_id = hashlib.sha256((content + xml_url).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": output, - } diff --git a/embedchain/embedchain/loaders/youtube_channel.py b/embedchain/embedchain/loaders/youtube_channel.py deleted file mode 100644 index ab235e19a..000000000 --- a/embedchain/embedchain/loaders/youtube_channel.py +++ /dev/null @@ -1,79 +0,0 @@ -import concurrent.futures -import hashlib -import logging - -from tqdm import tqdm - -from embedchain.loaders.base_loader import BaseLoader -from embedchain.loaders.youtube_video import YoutubeVideoLoader - -logger = logging.getLogger(__name__) - - -class YoutubeChannelLoader(BaseLoader): - """Loader for youtube channel.""" - - def load_data(self, channel_name): - try: - import yt_dlp - except ImportError as e: - raise ValueError( - "YoutubeChannelLoader requires extra dependencies. Install with `pip install yt_dlp==2023.11.14 youtube-transcript-api==0.6.1`" # noqa: E501 - ) from e - - data = [] - data_urls = [] - youtube_url = f"https://www.youtube.com/{channel_name}/videos" - youtube_video_loader = YoutubeVideoLoader() - - def _get_yt_video_links(): - try: - ydl_opts = { - "quiet": True, - "extract_flat": True, - } - with yt_dlp.YoutubeDL(ydl_opts) as ydl: - info_dict = ydl.extract_info(youtube_url, download=False) - if "entries" in info_dict: - videos = [entry["url"] for entry in info_dict["entries"]] - return videos - except Exception: - logger.error(f"Failed to fetch youtube videos for channel: {channel_name}") - return [] - - def _load_yt_video(video_link): - try: - each_load_data = youtube_video_loader.load_data(video_link) - if each_load_data: - return each_load_data.get("data") - except Exception as e: - logger.error(f"Failed to load youtube video {video_link}: {e}") - return None - - def _add_youtube_channel(): - video_links = _get_yt_video_links() - logger.info("Loading videos from youtube channel...") - with concurrent.futures.ThreadPoolExecutor() as executor: - # Submitting all tasks and storing the future object with the video link - future_to_video = { - executor.submit(_load_yt_video, video_link): video_link for video_link in video_links - } - - for future in tqdm( - concurrent.futures.as_completed(future_to_video), total=len(video_links), desc="Processing videos" - ): - video = future_to_video[future] - try: - results = future.result() - if results: - data.extend(results) - data_urls.extend([result.get("meta_data").get("url") for result in results]) - except Exception as e: - logger.error(f"Failed to process youtube video {video}: {e}") - - _add_youtube_channel() - doc_id = hashlib.sha256((youtube_url + ", ".join(data_urls)).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": data, - } diff --git a/embedchain/embedchain/loaders/youtube_video.py b/embedchain/embedchain/loaders/youtube_video.py deleted file mode 100644 index 44acc0fcf..000000000 --- a/embedchain/embedchain/loaders/youtube_video.py +++ /dev/null @@ -1,57 +0,0 @@ -import hashlib -import json -import logging - -try: - from youtube_transcript_api import YouTubeTranscriptApi -except ImportError: - raise ImportError("YouTube video requires extra dependencies. Install with `pip install youtube-transcript-api`") -try: - from langchain_community.document_loaders import YoutubeLoader - from langchain_community.document_loaders.youtube import _parse_video_id -except ImportError: - raise ImportError("YouTube video requires extra dependencies. Install with `pip install pytube==15.0.0`") from None -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.loaders.base_loader import BaseLoader -from embedchain.utils.misc import clean_string - - -@register_deserializable -class YoutubeVideoLoader(BaseLoader): - def load_data(self, url): - """Load data from a Youtube video.""" - video_id = _parse_video_id(url) - - languages = ["en"] - try: - # Fetching transcript data - languages = [transcript.language_code for transcript in YouTubeTranscriptApi.list_transcripts(video_id)] - transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=languages) - # convert transcript to json to avoid unicode symboles - transcript = json.dumps(transcript, ensure_ascii=True) - except Exception: - logging.exception(f"Failed to fetch transcript for video {url}") - transcript = "Unavailable" - - loader = YoutubeLoader.from_youtube_url(url, add_video_info=True, language=languages) - doc = loader.load() - output = [] - if not len(doc): - raise ValueError(f"No data found for url: {url}") - content = doc[0].page_content - content = clean_string(content) - metadata = doc[0].metadata - metadata["url"] = url - metadata["transcript"] = transcript - - output.append( - { - "content": content, - "meta_data": metadata, - } - ) - doc_id = hashlib.sha256((content + url).encode()).hexdigest() - return { - "doc_id": doc_id, - "data": output, - } diff --git a/embedchain/embedchain/memory/__init__.py b/embedchain/embedchain/memory/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/memory/base.py b/embedchain/embedchain/memory/base.py deleted file mode 100644 index d6697625d..000000000 --- a/embedchain/embedchain/memory/base.py +++ /dev/null @@ -1,127 +0,0 @@ -import json -import logging -import uuid -from typing import Any, Optional - -from embedchain.core.db.database import get_session -from embedchain.core.db.models import ChatHistory as ChatHistoryModel -from embedchain.memory.message import ChatMessage -from embedchain.memory.utils import merge_metadata_dict - -logger = logging.getLogger(__name__) - - -class ChatHistory: - def __init__(self) -> None: - self.db_session = get_session() - - def add(self, app_id, session_id, chat_message: ChatMessage) -> Optional[str]: - memory_id = str(uuid.uuid4()) - metadata_dict = merge_metadata_dict(chat_message.human_message.metadata, chat_message.ai_message.metadata) - if metadata_dict: - metadata = self._serialize_json(metadata_dict) - self.db_session.add( - ChatHistoryModel( - app_id=app_id, - id=memory_id, - session_id=session_id, - question=chat_message.human_message.content, - answer=chat_message.ai_message.content, - metadata=metadata if metadata_dict else "{}", - ) - ) - try: - self.db_session.commit() - except Exception as e: - logger.error(f"Error adding chat memory to db: {e}") - self.db_session.rollback() - return None - - logger.info(f"Added chat memory to db with id: {memory_id}") - return memory_id - - def delete(self, app_id: str, session_id: Optional[str] = None): - """ - Delete all chat history for a given app_id and session_id. - This is useful for deleting chat history for a given user. - - :param app_id: The app_id to delete chat history for - :param session_id: The session_id to delete chat history for - - :return: None - """ - params = {"app_id": app_id} - if session_id: - params["session_id"] = session_id - self.db_session.query(ChatHistoryModel).filter_by(**params).delete() - try: - self.db_session.commit() - except Exception as e: - logger.error(f"Error deleting chat history: {e}") - self.db_session.rollback() - - def get( - self, app_id, session_id: str = "default", num_rounds=10, fetch_all: bool = False, display_format=False - ) -> list[ChatMessage]: - """ - Get the chat history for a given app_id. - - param: app_id - The app_id to get chat history - param: session_id (optional) - The session_id to get chat history. Defaults to "default" - param: num_rounds (optional) - The number of rounds to get chat history. Defaults to 10 - param: fetch_all (optional) - Whether to fetch all chat history or not. Defaults to False - param: display_format (optional) - Whether to return the chat history in display format. Defaults to False - """ - params = {"app_id": app_id} - if not fetch_all: - params["session_id"] = session_id - results = ( - self.db_session.query(ChatHistoryModel).filter_by(**params).order_by(ChatHistoryModel.created_at.asc()) - ) - results = results.limit(num_rounds) if not fetch_all else results - history = [] - for result in results: - metadata = self._deserialize_json(metadata=result.meta_data or "{}") - # Return list of dict if display_format is True - if display_format: - history.append( - { - "session_id": result.session_id, - "human": result.question, - "ai": result.answer, - "metadata": result.meta_data, - "timestamp": result.created_at, - } - ) - else: - memory = ChatMessage() - memory.add_user_message(result.question, metadata=metadata) - memory.add_ai_message(result.answer, metadata=metadata) - history.append(memory) - return history - - def count(self, app_id: str, session_id: Optional[str] = None): - """ - Count the number of chat messages for a given app_id and session_id. - - :param app_id: The app_id to count chat history for - :param session_id: The session_id to count chat history for - - :return: The number of chat messages for a given app_id and session_id - """ - # Rewrite the logic below with sqlalchemy - params = {"app_id": app_id} - if session_id: - params["session_id"] = session_id - return self.db_session.query(ChatHistoryModel).filter_by(**params).count() - - @staticmethod - def _serialize_json(metadata: dict[str, Any]): - return json.dumps(metadata) - - @staticmethod - def _deserialize_json(metadata: str): - return json.loads(metadata) - - def close_connection(self): - self.connection.close() diff --git a/embedchain/embedchain/memory/message.py b/embedchain/embedchain/memory/message.py deleted file mode 100644 index 5211b0f6a..000000000 --- a/embedchain/embedchain/memory/message.py +++ /dev/null @@ -1,74 +0,0 @@ -import logging -from typing import Any, Optional - -from embedchain.helpers.json_serializable import JSONSerializable - -logger = logging.getLogger(__name__) - - -class BaseMessage(JSONSerializable): - """ - The base abstract message class. - - Messages are the inputs and outputs of Models. - """ - - # The string content of the message. - content: str - - # The created_by of the message. AI, Human, Bot etc. - created_by: str - - # Any additional info. - metadata: dict[str, Any] - - def __init__(self, content: str, created_by: str, metadata: Optional[dict[str, Any]] = None) -> None: - super().__init__() - self.content = content - self.created_by = created_by - self.metadata = metadata - - @property - def type(self) -> str: - """Type of the Message, used for serialization.""" - - @classmethod - def is_lc_serializable(cls) -> bool: - """Return whether this class is serializable.""" - return True - - def __str__(self) -> str: - return f"{self.created_by}: {self.content}" - - -class ChatMessage(JSONSerializable): - """ - The base abstract chat message class. - - Chat messages are the pair of (question, answer) conversation - between human and model. - """ - - human_message: Optional[BaseMessage] = None - ai_message: Optional[BaseMessage] = None - - def add_user_message(self, message: str, metadata: Optional[dict] = None): - if self.human_message: - logger.info( - "Human message already exists in the chat message,\ - overwriting it with new message." - ) - - self.human_message = BaseMessage(content=message, created_by="human", metadata=metadata) - - def add_ai_message(self, message: str, metadata: Optional[dict] = None): - if self.ai_message: - logger.info( - "AI message already exists in the chat message,\ - overwriting it with new message." - ) - - self.ai_message = BaseMessage(content=message, created_by="ai", metadata=metadata) - - def __str__(self) -> str: - return f"{self.human_message}\n{self.ai_message}" diff --git a/embedchain/embedchain/memory/utils.py b/embedchain/embedchain/memory/utils.py deleted file mode 100644 index b849cffa6..000000000 --- a/embedchain/embedchain/memory/utils.py +++ /dev/null @@ -1,35 +0,0 @@ -from typing import Any, Optional - - -def merge_metadata_dict(left: Optional[dict[str, Any]], right: Optional[dict[str, Any]]) -> Optional[dict[str, Any]]: - """ - Merge the metadatas of two BaseMessage types. - - Args: - left (dict[str, Any]): metadata of human message - right (dict[str, Any]): metadata of AI message - - Returns: - dict[str, Any]: combined metadata dict with dedup - to be saved in db. - """ - if not left and not right: - return None - elif not left: - return right - elif not right: - return left - - merged = left.copy() - for k, v in right.items(): - if k not in merged: - merged[k] = v - elif type(merged[k]) is not type(v): - raise ValueError(f'additional_kwargs["{k}"] already exists in this message,' " but with a different type.") - elif isinstance(merged[k], str): - merged[k] += v - elif isinstance(merged[k], dict): - merged[k] = merge_metadata_dict(merged[k], v) - else: - raise ValueError(f"Additional kwargs key {k} already exists in this message.") - return merged diff --git a/embedchain/embedchain/migrations/env.py b/embedchain/embedchain/migrations/env.py deleted file mode 100644 index 8fb3cd805..000000000 --- a/embedchain/embedchain/migrations/env.py +++ /dev/null @@ -1,68 +0,0 @@ -import os - -from alembic import context -from sqlalchemy import engine_from_config, pool - -from embedchain.core.db.models import Base - -# this is the Alembic Config object, which provides -# access to the values within the .ini file in use. -config = context.config - -target_metadata = Base.metadata - -# other values from the config, defined by the needs of env.py, -# can be acquired: -# my_important_option = config.get_main_option("my_important_option") -# ... etc. -config.set_main_option("sqlalchemy.url", os.environ.get("EMBEDCHAIN_DB_URI")) - - -def run_migrations_offline() -> None: - """Run migrations in 'offline' mode. - - This configures the context with just a URL - and not an Engine, though an Engine is acceptable - here as well. By skipping the Engine creation - we don't even need a DBAPI to be available. - - Calls to context.execute() here emit the given string to the - script output. - - """ - url = config.get_main_option("sqlalchemy.url") - context.configure( - url=url, - target_metadata=target_metadata, - literal_binds=True, - dialect_opts={"paramstyle": "named"}, - ) - - with context.begin_transaction(): - context.run_migrations() - - -def run_migrations_online() -> None: - """Run migrations in 'online' mode. - - In this scenario we need to create an Engine - and associate a connection with the context. - - """ - connectable = engine_from_config( - config.get_section(config.config_ini_section, {}), - prefix="sqlalchemy.", - poolclass=pool.NullPool, - ) - - with connectable.connect() as connection: - context.configure(connection=connection, target_metadata=target_metadata) - - with context.begin_transaction(): - context.run_migrations() - - -if context.is_offline_mode(): - run_migrations_offline() -else: - run_migrations_online() diff --git a/embedchain/embedchain/migrations/script.py.mako b/embedchain/embedchain/migrations/script.py.mako deleted file mode 100644 index fbc4b07dc..000000000 --- a/embedchain/embedchain/migrations/script.py.mako +++ /dev/null @@ -1,26 +0,0 @@ -"""${message} - -Revision ID: ${up_revision} -Revises: ${down_revision | comma,n} -Create Date: ${create_date} - -""" -from typing import Sequence, Union - -from alembic import op -import sqlalchemy as sa -${imports if imports else ""} - -# revision identifiers, used by Alembic. -revision: str = ${repr(up_revision)} -down_revision: Union[str, None] = ${repr(down_revision)} -branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)} -depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)} - - -def upgrade() -> None: - ${upgrades if upgrades else "pass"} - - -def downgrade() -> None: - ${downgrades if downgrades else "pass"} diff --git a/embedchain/embedchain/migrations/versions/40a327b3debd_create_initial_migrations.py b/embedchain/embedchain/migrations/versions/40a327b3debd_create_initial_migrations.py deleted file mode 100644 index 1facc88e3..000000000 --- a/embedchain/embedchain/migrations/versions/40a327b3debd_create_initial_migrations.py +++ /dev/null @@ -1,62 +0,0 @@ -"""Create initial migrations - -Revision ID: 40a327b3debd -Revises: -Create Date: 2024-02-18 15:29:19.409064 - -""" - -from typing import Sequence, Union - -import sqlalchemy as sa -from alembic import op - -# revision identifiers, used by Alembic. -revision: str = "40a327b3debd" -down_revision: Union[str, None] = None -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None - - -def upgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.create_table( - "ec_chat_history", - sa.Column("app_id", sa.String(), nullable=False), - sa.Column("id", sa.String(), nullable=False), - sa.Column("session_id", sa.String(), nullable=False), - sa.Column("question", sa.Text(), nullable=True), - sa.Column("answer", sa.Text(), nullable=True), - sa.Column("metadata", sa.Text(), nullable=True), - sa.Column("created_at", sa.TIMESTAMP(), nullable=True), - sa.PrimaryKeyConstraint("app_id", "id", "session_id"), - ) - op.create_index(op.f("ix_ec_chat_history_created_at"), "ec_chat_history", ["created_at"], unique=False) - op.create_index(op.f("ix_ec_chat_history_session_id"), "ec_chat_history", ["session_id"], unique=False) - op.create_table( - "ec_data_sources", - sa.Column("id", sa.String(), nullable=False), - sa.Column("app_id", sa.Text(), nullable=True), - sa.Column("hash", sa.Text(), nullable=True), - sa.Column("type", sa.Text(), nullable=True), - sa.Column("value", sa.Text(), nullable=True), - sa.Column("metadata", sa.Text(), nullable=True), - sa.Column("is_uploaded", sa.Integer(), nullable=True), - sa.PrimaryKeyConstraint("id"), - ) - op.create_index(op.f("ix_ec_data_sources_hash"), "ec_data_sources", ["hash"], unique=False) - op.create_index(op.f("ix_ec_data_sources_app_id"), "ec_data_sources", ["app_id"], unique=False) - op.create_index(op.f("ix_ec_data_sources_type"), "ec_data_sources", ["type"], unique=False) - # ### end Alembic commands ### - - -def downgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.drop_index(op.f("ix_ec_data_sources_type"), table_name="ec_data_sources") - op.drop_index(op.f("ix_ec_data_sources_app_id"), table_name="ec_data_sources") - op.drop_index(op.f("ix_ec_data_sources_hash"), table_name="ec_data_sources") - op.drop_table("ec_data_sources") - op.drop_index(op.f("ix_ec_chat_history_session_id"), table_name="ec_chat_history") - op.drop_index(op.f("ix_ec_chat_history_created_at"), table_name="ec_chat_history") - op.drop_table("ec_chat_history") - # ### end Alembic commands ### diff --git a/embedchain/embedchain/models/__init__.py b/embedchain/embedchain/models/__init__.py deleted file mode 100644 index 48887545b..000000000 --- a/embedchain/embedchain/models/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .embedding_functions import EmbeddingFunctions # noqa: F401 -from .providers import Providers # noqa: F401 -from .vector_dimensions import VectorDimensions # noqa: F401 diff --git a/embedchain/embedchain/models/data_type.py b/embedchain/embedchain/models/data_type.py deleted file mode 100644 index 6370bf064..000000000 --- a/embedchain/embedchain/models/data_type.py +++ /dev/null @@ -1,85 +0,0 @@ -from enum import Enum - - -class DirectDataType(Enum): - """ - DirectDataType enum contains data types that contain raw data directly. - """ - - TEXT = "text" - - -class IndirectDataType(Enum): - """ - IndirectDataType enum contains data types that contain references to data stored elsewhere. - """ - - YOUTUBE_VIDEO = "youtube_video" - PDF_FILE = "pdf_file" - WEB_PAGE = "web_page" - SITEMAP = "sitemap" - XML = "xml" - DOCX = "docx" - DOCS_SITE = "docs_site" - NOTION = "notion" - CSV = "csv" - MDX = "mdx" - IMAGE = "image" - UNSTRUCTURED = "unstructured" - JSON = "json" - OPENAPI = "openapi" - GMAIL = "gmail" - SUBSTACK = "substack" - YOUTUBE_CHANNEL = "youtube_channel" - DISCORD = "discord" - CUSTOM = "custom" - RSSFEED = "rss_feed" - BEEHIIV = "beehiiv" - GOOGLE_DRIVE = "google_drive" - DIRECTORY = "directory" - SLACK = "slack" - DROPBOX = "dropbox" - TEXT_FILE = "text_file" - EXCEL_FILE = "excel_file" - AUDIO = "audio" - - -class SpecialDataType(Enum): - """ - SpecialDataType enum contains data types that are neither direct nor indirect, or simply require special attention. - """ - - QNA_PAIR = "qna_pair" - - -class DataType(Enum): - TEXT = DirectDataType.TEXT.value - YOUTUBE_VIDEO = IndirectDataType.YOUTUBE_VIDEO.value - PDF_FILE = IndirectDataType.PDF_FILE.value - WEB_PAGE = IndirectDataType.WEB_PAGE.value - SITEMAP = IndirectDataType.SITEMAP.value - XML = IndirectDataType.XML.value - DOCX = IndirectDataType.DOCX.value - DOCS_SITE = IndirectDataType.DOCS_SITE.value - NOTION = IndirectDataType.NOTION.value - CSV = IndirectDataType.CSV.value - MDX = IndirectDataType.MDX.value - QNA_PAIR = SpecialDataType.QNA_PAIR.value - IMAGE = IndirectDataType.IMAGE.value - UNSTRUCTURED = IndirectDataType.UNSTRUCTURED.value - JSON = IndirectDataType.JSON.value - OPENAPI = IndirectDataType.OPENAPI.value - GMAIL = IndirectDataType.GMAIL.value - SUBSTACK = IndirectDataType.SUBSTACK.value - YOUTUBE_CHANNEL = IndirectDataType.YOUTUBE_CHANNEL.value - DISCORD = IndirectDataType.DISCORD.value - CUSTOM = IndirectDataType.CUSTOM.value - RSSFEED = IndirectDataType.RSSFEED.value - BEEHIIV = IndirectDataType.BEEHIIV.value - GOOGLE_DRIVE = IndirectDataType.GOOGLE_DRIVE.value - DIRECTORY = IndirectDataType.DIRECTORY.value - SLACK = IndirectDataType.SLACK.value - DROPBOX = IndirectDataType.DROPBOX.value - TEXT_FILE = IndirectDataType.TEXT_FILE.value - EXCEL_FILE = IndirectDataType.EXCEL_FILE.value - AUDIO = IndirectDataType.AUDIO.value diff --git a/embedchain/embedchain/models/embedding_functions.py b/embedchain/embedchain/models/embedding_functions.py deleted file mode 100644 index 7171fadfa..000000000 --- a/embedchain/embedchain/models/embedding_functions.py +++ /dev/null @@ -1,10 +0,0 @@ -from enum import Enum - - -class EmbeddingFunctions(Enum): - OPENAI = "OPENAI" - HUGGING_FACE = "HUGGING_FACE" - VERTEX_AI = "VERTEX_AI" - AWS_BEDROCK = "AWS_BEDROCK" - GPT4ALL = "GPT4ALL" - OLLAMA = "OLLAMA" diff --git a/embedchain/embedchain/models/providers.py b/embedchain/embedchain/models/providers.py deleted file mode 100644 index 62c93675b..000000000 --- a/embedchain/embedchain/models/providers.py +++ /dev/null @@ -1,10 +0,0 @@ -from enum import Enum - - -class Providers(Enum): - OPENAI = "OPENAI" - ANTHROPHIC = "ANTHPROPIC" - VERTEX_AI = "VERTEX_AI" - GPT4ALL = "GPT4ALL" - OLLAMA = "OLLAMA" - AZURE_OPENAI = "AZURE_OPENAI" diff --git a/embedchain/embedchain/models/vector_dimensions.py b/embedchain/embedchain/models/vector_dimensions.py deleted file mode 100644 index bdea70756..000000000 --- a/embedchain/embedchain/models/vector_dimensions.py +++ /dev/null @@ -1,16 +0,0 @@ -from enum import Enum - - -# vector length created by embedding fn -class VectorDimensions(Enum): - GPT4ALL = 384 - OPENAI = 1536 - VERTEX_AI = 768 - HUGGING_FACE = 384 - GOOGLE_AI = 768 - MISTRAL_AI = 1024 - NVIDIA_AI = 1024 - COHERE = 384 - OLLAMA = 384 - AMAZON_TITAN_V1 = 1536 - AMAZON_TITAN_V2 = 1024 diff --git a/embedchain/embedchain/pipeline.py b/embedchain/embedchain/pipeline.py deleted file mode 100644 index 6f70bfb5d..000000000 --- a/embedchain/embedchain/pipeline.py +++ /dev/null @@ -1,9 +0,0 @@ -from embedchain.app import App - - -class Pipeline(App): - """ - This is deprecated. Use `App` instead. - """ - - pass diff --git a/embedchain/embedchain/store/__init__.py b/embedchain/embedchain/store/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/store/assistants.py b/embedchain/embedchain/store/assistants.py deleted file mode 100644 index b9ca151ab..000000000 --- a/embedchain/embedchain/store/assistants.py +++ /dev/null @@ -1,206 +0,0 @@ -import logging -import os -import re -import tempfile -import time -import uuid -from pathlib import Path -from typing import cast - -from openai import OpenAI -from openai.types.beta.threads import Message -from openai.types.beta.threads.text_content_block import TextContentBlock - -from embedchain import Client, Pipeline -from embedchain.config import AddConfig -from embedchain.data_formatter import DataFormatter -from embedchain.models.data_type import DataType -from embedchain.telemetry.posthog import AnonymousTelemetry -from embedchain.utils.misc import detect_datatype - -# Set up the user directory if it doesn't exist already -Client.setup() - - -class OpenAIAssistant: - def __init__( - self, - name=None, - instructions=None, - tools=None, - thread_id=None, - model="gpt-4-1106-preview", - data_sources=None, - assistant_id=None, - log_level=logging.INFO, - collect_metrics=True, - ): - self.name = name or "OpenAI Assistant" - self.instructions = instructions - self.tools = tools or [{"type": "retrieval"}] - self.model = model - self.data_sources = data_sources or [] - self.log_level = log_level - self._client = OpenAI() - self._initialize_assistant(assistant_id) - self.thread_id = thread_id or self._create_thread() - self._telemetry_props = {"class": self.__class__.__name__} - self.telemetry = AnonymousTelemetry(enabled=collect_metrics) - self.telemetry.capture(event_name="init", properties=self._telemetry_props) - - def add(self, source, data_type=None): - file_path = self._prepare_source_path(source, data_type) - self._add_file_to_assistant(file_path) - - event_props = { - **self._telemetry_props, - "data_type": data_type or detect_datatype(source), - } - self.telemetry.capture(event_name="add", properties=event_props) - logging.info("Data successfully added to the assistant.") - - def chat(self, message): - self._send_message(message) - self.telemetry.capture(event_name="chat", properties=self._telemetry_props) - return self._get_latest_response() - - def delete_thread(self): - self._client.beta.threads.delete(self.thread_id) - self.thread_id = self._create_thread() - - # Internal methods - def _initialize_assistant(self, assistant_id): - file_ids = self._generate_file_ids(self.data_sources) - self.assistant = ( - self._client.beta.assistants.retrieve(assistant_id) - if assistant_id - else self._client.beta.assistants.create( - name=self.name, model=self.model, file_ids=file_ids, instructions=self.instructions, tools=self.tools - ) - ) - - def _create_thread(self): - thread = self._client.beta.threads.create() - return thread.id - - def _prepare_source_path(self, source, data_type=None): - if Path(source).is_file(): - return source - data_type = data_type or detect_datatype(source) - formatter = DataFormatter(data_type=DataType(data_type), config=AddConfig()) - data = formatter.loader.load_data(source)["data"] - return self._save_temp_data(data=data[0]["content"].encode(), source=source) - - def _add_file_to_assistant(self, file_path): - file_obj = self._client.files.create(file=open(file_path, "rb"), purpose="assistants") - self._client.beta.assistants.files.create(assistant_id=self.assistant.id, file_id=file_obj.id) - - def _generate_file_ids(self, data_sources): - return [ - self._add_file_to_assistant(self._prepare_source_path(ds["source"], ds.get("data_type"))) - for ds in data_sources - ] - - def _send_message(self, message): - self._client.beta.threads.messages.create(thread_id=self.thread_id, role="user", content=message) - self._wait_for_completion() - - def _wait_for_completion(self): - run = self._client.beta.threads.runs.create( - thread_id=self.thread_id, - assistant_id=self.assistant.id, - instructions=self.instructions, - ) - run_id = run.id - run_status = run.status - - while run_status in ["queued", "in_progress", "requires_action"]: - time.sleep(0.1) # Sleep before making the next API call to avoid hitting rate limits - run = self._client.beta.threads.runs.retrieve(thread_id=self.thread_id, run_id=run_id) - run_status = run.status - if run_status == "failed": - raise ValueError(f"Thread run failed with the following error: {run.last_error}") - - def _get_latest_response(self): - history = self._get_history() - return self._format_message(history[0]) if history else None - - def _get_history(self): - messages = self._client.beta.threads.messages.list(thread_id=self.thread_id, order="desc") - return list(messages) - - @staticmethod - def _format_message(thread_message): - thread_message = cast(Message, thread_message) - content = [c.text.value for c in thread_message.content if isinstance(c, TextContentBlock)] - return " ".join(content) - - @staticmethod - def _save_temp_data(data, source): - special_chars_pattern = r'[\\/:*?"<>|&=% ]+' - sanitized_source = re.sub(special_chars_pattern, "_", source)[:256] - temp_dir = tempfile.mkdtemp() - file_path = os.path.join(temp_dir, sanitized_source) - with open(file_path, "wb") as file: - file.write(data) - return file_path - - -class AIAssistant: - def __init__( - self, - name=None, - instructions=None, - yaml_path=None, - assistant_id=None, - thread_id=None, - data_sources=None, - log_level=logging.INFO, - collect_metrics=True, - ): - self.name = name or "AI Assistant" - self.data_sources = data_sources or [] - self.log_level = log_level - self.instructions = instructions - self.assistant_id = assistant_id or str(uuid.uuid4()) - self.thread_id = thread_id or str(uuid.uuid4()) - self.pipeline = Pipeline.from_config(config_path=yaml_path) if yaml_path else Pipeline() - self.pipeline.local_id = self.pipeline.config.id = self.thread_id - - if self.instructions: - self.pipeline.system_prompt = self.instructions - - print( - f"🎉 Created AI Assistant with name: {self.name}, assistant_id: {self.assistant_id}, thread_id: {self.thread_id}" # noqa: E501 - ) - - # telemetry related properties - self._telemetry_props = {"class": self.__class__.__name__} - self.telemetry = AnonymousTelemetry(enabled=collect_metrics) - self.telemetry.capture(event_name="init", properties=self._telemetry_props) - - if self.data_sources: - for data_source in self.data_sources: - metadata = {"assistant_id": self.assistant_id, "thread_id": "global_knowledge"} - self.pipeline.add(data_source["source"], data_source.get("data_type"), metadata=metadata) - - def add(self, source, data_type=None): - metadata = {"assistant_id": self.assistant_id, "thread_id": self.thread_id} - self.pipeline.add(source, data_type=data_type, metadata=metadata) - event_props = { - **self._telemetry_props, - "data_type": data_type or detect_datatype(source), - } - self.telemetry.capture(event_name="add", properties=event_props) - - def chat(self, query): - where = { - "$and": [ - {"assistant_id": {"$eq": self.assistant_id}}, - {"thread_id": {"$in": [self.thread_id, "global_knowledge"]}}, - ] - } - return self.pipeline.chat(query, where=where) - - def delete(self): - self.pipeline.reset() diff --git a/embedchain/embedchain/telemetry/__init__.py b/embedchain/embedchain/telemetry/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/telemetry/posthog.py b/embedchain/embedchain/telemetry/posthog.py deleted file mode 100644 index 37c63ea61..000000000 --- a/embedchain/embedchain/telemetry/posthog.py +++ /dev/null @@ -1,60 +0,0 @@ -import json -import logging -import os -import uuid - -from posthog import Posthog - -import embedchain -from embedchain.constants import CONFIG_DIR, CONFIG_FILE - - -class AnonymousTelemetry: - def __init__(self, host="https://app.posthog.com", enabled=True): - self.project_api_key = "phc_PHQDA5KwztijnSojsxJ2c1DuJd52QCzJzT2xnSGvjN2" - self.host = host - self.posthog = Posthog(project_api_key=self.project_api_key, host=self.host) - self.user_id = self._get_user_id() - self.enabled = enabled - - # Check if telemetry tracking is disabled via environment variable - if "EC_TELEMETRY" in os.environ and os.environ["EC_TELEMETRY"].lower() not in [ - "1", - "true", - "yes", - ]: - self.enabled = False - - if not self.enabled: - self.posthog.disabled = True - - # Silence posthog logging - posthog_logger = logging.getLogger("posthog") - posthog_logger.disabled = True - - @staticmethod - def _get_user_id(): - os.makedirs(CONFIG_DIR, exist_ok=True) - if os.path.exists(CONFIG_FILE): - with open(CONFIG_FILE, "r") as f: - data = json.load(f) - if "user_id" in data: - return data["user_id"] - - user_id = str(uuid.uuid4()) - with open(CONFIG_FILE, "w") as f: - json.dump({"user_id": user_id}, f) - return user_id - - def capture(self, event_name, properties=None): - default_properties = { - "version": embedchain.__version__, - "language": "python", - "pid": os.getpid(), - } - properties.update(default_properties) - - try: - self.posthog.capture(self.user_id, event_name, properties) - except Exception: - logging.exception(f"Failed to send telemetry {event_name=}") diff --git a/embedchain/embedchain/utils/__init__.py b/embedchain/embedchain/utils/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/utils/cli.py b/embedchain/embedchain/utils/cli.py deleted file mode 100644 index 13128df5a..000000000 --- a/embedchain/embedchain/utils/cli.py +++ /dev/null @@ -1,320 +0,0 @@ -import os -import re -import shutil -import subprocess - -import pkg_resources -from rich.console import Console - -console = Console() - - -def get_pkg_path_from_name(template: str): - try: - # Determine the installation location of the embedchain package - package_path = pkg_resources.resource_filename("embedchain", "") - except ImportError: - console.print("❌ [bold red]Failed to locate the 'embedchain' package. Is it installed?[/bold red]") - return - - # Construct the source path from the embedchain package - src_path = os.path.join(package_path, "deployment", template) - - if not os.path.exists(src_path): - console.print(f"❌ [bold red]Template '{template}' not found.[/bold red]") - return - - return src_path - - -def setup_fly_io_app(extra_args): - fly_launch_command = ["fly", "launch", "--region", "sjc", "--no-deploy"] + list(extra_args) - try: - console.print(f"🚀 [bold cyan]Running: {' '.join(fly_launch_command)}[/bold cyan]") - shutil.move(".env.example", ".env") - subprocess.run(fly_launch_command, check=True) - console.print("✅ [bold green]'fly launch' executed successfully.[/bold green]") - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except FileNotFoundError: - console.print( - "❌ [bold red]'fly' command not found. Please ensure Fly CLI is installed and in your PATH.[/bold red]" - ) - - -def setup_modal_com_app(extra_args): - modal_setup_file = os.path.join(os.path.expanduser("~"), ".modal.toml") - if os.path.exists(modal_setup_file): - console.print( - """✅ [bold green]Modal setup already done. You can now install the dependencies by doing \n - `pip install -r requirements.txt`[/bold green]""" - ) - else: - modal_setup_cmd = ["modal", "setup"] + list(extra_args) - console.print(f"🚀 [bold cyan]Running: {' '.join(modal_setup_cmd)}[/bold cyan]") - subprocess.run(modal_setup_cmd, check=True) - shutil.move(".env.example", ".env") - console.print( - """Great! Now you can install the dependencies by doing: \n - `pip install -r requirements.txt`\n - \n - To run your app locally:\n - `ec dev` - """ - ) - - -def setup_render_com_app(): - render_setup_file = os.path.join(os.path.expanduser("~"), ".render/config.yaml") - if os.path.exists(render_setup_file): - console.print( - """✅ [bold green]Render setup already done. You can now install the dependencies by doing \n - `pip install -r requirements.txt`[/bold green]""" - ) - else: - render_setup_cmd = ["render", "config", "init"] - console.print(f"🚀 [bold cyan]Running: {' '.join(render_setup_cmd)}[/bold cyan]") - subprocess.run(render_setup_cmd, check=True) - shutil.move(".env.example", ".env") - console.print( - """Great! Now you can install the dependencies by doing: \n - `pip install -r requirements.txt`\n - \n - To run your app locally:\n - `ec dev` - """ - ) - - -def setup_streamlit_io_app(): - # nothing needs to be done here - console.print("Great! Now you can install the dependencies by doing `pip install -r requirements.txt`") - - -def setup_gradio_app(): - # nothing needs to be done here - console.print("Great! Now you can install the dependencies by doing `pip install -r requirements.txt`") - - -def setup_hf_app(): - subprocess.run(["pip", "install", "huggingface_hub[cli]"], check=True) - hf_setup_file = os.path.join(os.path.expanduser("~"), ".cache/huggingface/token") - if os.path.exists(hf_setup_file): - console.print( - """✅ [bold green]HuggingFace setup already done. You can now install the dependencies by doing \n - `pip install -r requirements.txt`[/bold green]""" - ) - else: - console.print( - """🚀 [cyan]Running: huggingface-cli login \n - Please provide a [bold]WRITE[/bold] token so that we can directly deploy\n - your apps from the terminal.[/cyan] - """ - ) - subprocess.run(["huggingface-cli", "login"], check=True) - console.print("Great! Now you can install the dependencies by doing `pip install -r requirements.txt`") - - -def run_dev_fly_io(debug, host, port): - uvicorn_command = ["uvicorn", "app:app"] - - if debug: - uvicorn_command.append("--reload") - - uvicorn_command.extend(["--host", host, "--port", str(port)]) - - try: - console.print(f"🚀 [bold cyan]Running FastAPI app with command: {' '.join(uvicorn_command)}[/bold cyan]") - subprocess.run(uvicorn_command, check=True) - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except KeyboardInterrupt: - console.print("\n🛑 [bold yellow]FastAPI server stopped[/bold yellow]") - - -def run_dev_modal_com(): - modal_run_cmd = ["modal", "serve", "app"] - try: - console.print(f"🚀 [bold cyan]Running FastAPI app with command: {' '.join(modal_run_cmd)}[/bold cyan]") - subprocess.run(modal_run_cmd, check=True) - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except KeyboardInterrupt: - console.print("\n🛑 [bold yellow]FastAPI server stopped[/bold yellow]") - - -def run_dev_streamlit_io(): - streamlit_run_cmd = ["streamlit", "run", "app.py"] - try: - console.print(f"🚀 [bold cyan]Running Streamlit app with command: {' '.join(streamlit_run_cmd)}[/bold cyan]") - subprocess.run(streamlit_run_cmd, check=True) - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except KeyboardInterrupt: - console.print("\n🛑 [bold yellow]Streamlit server stopped[/bold yellow]") - - -def run_dev_render_com(debug, host, port): - uvicorn_command = ["uvicorn", "app:app"] - - if debug: - uvicorn_command.append("--reload") - - uvicorn_command.extend(["--host", host, "--port", str(port)]) - - try: - console.print(f"🚀 [bold cyan]Running FastAPI app with command: {' '.join(uvicorn_command)}[/bold cyan]") - subprocess.run(uvicorn_command, check=True) - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except KeyboardInterrupt: - console.print("\n🛑 [bold yellow]FastAPI server stopped[/bold yellow]") - - -def run_dev_gradio(): - gradio_run_cmd = ["gradio", "app.py"] - try: - console.print(f"🚀 [bold cyan]Running Gradio app with command: {' '.join(gradio_run_cmd)}[/bold cyan]") - subprocess.run(gradio_run_cmd, check=True) - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except KeyboardInterrupt: - console.print("\n🛑 [bold yellow]Gradio server stopped[/bold yellow]") - - -def read_env_file(env_file_path): - """ - Reads an environment file and returns a dictionary of key-value pairs. - - Args: - env_file_path (str): The path to the .env file. - - Returns: - dict: Dictionary of environment variables. - """ - env_vars = {} - pattern = re.compile(r"(\w+)=(.*)") # compile regular expression for better performance - with open(env_file_path, "r") as file: - lines = file.readlines() # readlines is faster as it reads all at once - for line in lines: - line = line.strip() - # Ignore comments and empty lines - if line and not line.startswith("#"): - # Assume each line is in the format KEY=VALUE - key_value_match = pattern.match(line) - if key_value_match: - key, value = key_value_match.groups() - env_vars[key] = value - return env_vars - - -def deploy_fly(): - app_name = "" - with open("fly.toml", "r") as file: - for line in file: - if line.strip().startswith("app ="): - app_name = line.split("=")[1].strip().strip('"') - - if not app_name: - console.print("❌ [bold red]App name not found in fly.toml[/bold red]") - return - - env_vars = read_env_file(".env") - secrets_command = ["flyctl", "secrets", "set", "-a", app_name] + [f"{k}={v}" for k, v in env_vars.items()] - - deploy_command = ["fly", "deploy"] - try: - # Set secrets - console.print(f"🔐 [bold cyan]Setting secrets for {app_name}[/bold cyan]") - subprocess.run(secrets_command, check=True) - - # Deploy application - console.print(f"🚀 [bold cyan]Running: {' '.join(deploy_command)}[/bold cyan]") - subprocess.run(deploy_command, check=True) - console.print("✅ [bold green]'fly deploy' executed successfully.[/bold green]") - - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except FileNotFoundError: - console.print( - "❌ [bold red]'fly' command not found. Please ensure Fly CLI is installed and in your PATH.[/bold red]" - ) - - -def deploy_modal(): - modal_deploy_cmd = ["modal", "deploy", "app"] - try: - console.print(f"🚀 [bold cyan]Running: {' '.join(modal_deploy_cmd)}[/bold cyan]") - subprocess.run(modal_deploy_cmd, check=True) - console.print("✅ [bold green]'modal deploy' executed successfully.[/bold green]") - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except FileNotFoundError: - console.print( - "❌ [bold red]'modal' command not found. Please ensure Modal CLI is installed and in your PATH.[/bold red]" - ) - - -def deploy_streamlit(): - streamlit_deploy_cmd = ["streamlit", "run", "app.py"] - try: - console.print(f"🚀 [bold cyan]Running: {' '.join(streamlit_deploy_cmd)}[/bold cyan]") - console.print( - """\n\n✅ [bold yellow]To deploy a streamlit app, you can directly it from the UI.\n - Click on the 'Deploy' button on the top right corner of the app.\n - For more information, please refer to https://docs.embedchain.ai/deployment/streamlit_io - [/bold yellow] - \n\n""" - ) - subprocess.run(streamlit_deploy_cmd, check=True) - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except FileNotFoundError: - console.print( - """❌ [bold red]'streamlit' command not found.\n - Please ensure Streamlit CLI is installed and in your PATH.[/bold red]""" - ) - - -def deploy_render(): - render_deploy_cmd = ["render", "blueprint", "launch"] - - try: - console.print(f"🚀 [bold cyan]Running: {' '.join(render_deploy_cmd)}[/bold cyan]") - subprocess.run(render_deploy_cmd, check=True) - console.print("✅ [bold green]'render blueprint launch' executed successfully.[/bold green]") - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except FileNotFoundError: - console.print( - "❌ [bold red]'render' command not found. Please ensure Render CLI is installed and in your PATH.[/bold red]" # noqa:E501 - ) - - -def deploy_gradio_app(): - gradio_deploy_cmd = ["gradio", "deploy"] - - try: - console.print(f"🚀 [bold cyan]Running: {' '.join(gradio_deploy_cmd)}[/bold cyan]") - subprocess.run(gradio_deploy_cmd, check=True) - console.print("✅ [bold green]'gradio deploy' executed successfully.[/bold green]") - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") - except FileNotFoundError: - console.print( - "❌ [bold red]'gradio' command not found. Please ensure Gradio CLI is installed and in your PATH.[/bold red]" # noqa:E501 - ) - - -def deploy_hf_spaces(ec_app_name): - if not ec_app_name: - console.print("❌ [bold red]'name' not found in embedchain.json[/bold red]") - return - hf_spaces_deploy_cmd = ["huggingface-cli", "upload", ec_app_name, ".", ".", "--repo-type=space"] - - try: - console.print(f"🚀 [bold cyan]Running: {' '.join(hf_spaces_deploy_cmd)}[/bold cyan]") - subprocess.run(hf_spaces_deploy_cmd, check=True) - console.print("✅ [bold green]'huggingface-cli upload' executed successfully.[/bold green]") - except subprocess.CalledProcessError as e: - console.print(f"❌ [bold red]An error occurred: {e}[/bold red]") diff --git a/embedchain/embedchain/utils/evaluation.py b/embedchain/embedchain/utils/evaluation.py deleted file mode 100644 index 62eaaeb70..000000000 --- a/embedchain/embedchain/utils/evaluation.py +++ /dev/null @@ -1,17 +0,0 @@ -from enum import Enum -from typing import Optional - -from pydantic import BaseModel - - -class EvalMetric(Enum): - CONTEXT_RELEVANCY = "context_relevancy" - ANSWER_RELEVANCY = "answer_relevancy" - GROUNDEDNESS = "groundedness" - - -class EvalData(BaseModel): - question: str - contexts: list[str] - answer: str - ground_truth: Optional[str] = None # Not used as of now diff --git a/embedchain/embedchain/utils/misc.py b/embedchain/embedchain/utils/misc.py deleted file mode 100644 index 7c5468ec9..000000000 --- a/embedchain/embedchain/utils/misc.py +++ /dev/null @@ -1,546 +0,0 @@ -import datetime -import itertools -import json -import logging -import os -import re -import string -from typing import Any - -from schema import Optional, Or, Schema -from tqdm import tqdm - -from embedchain.models.data_type import DataType - -logger = logging.getLogger(__name__) - - -def parse_content(content, type): - implemented = ["html.parser", "lxml", "lxml-xml", "xml", "html5lib"] - if type not in implemented: - raise ValueError(f"Parser type {type} not implemented. Please choose one of {implemented}") - - from bs4 import BeautifulSoup - - soup = BeautifulSoup(content, type) - original_size = len(str(soup.get_text())) - - tags_to_exclude = [ - "nav", - "aside", - "form", - "header", - "noscript", - "svg", - "canvas", - "footer", - "script", - "style", - ] - for tag in soup(tags_to_exclude): - tag.decompose() - - ids_to_exclude = ["sidebar", "main-navigation", "menu-main-menu"] - for id in ids_to_exclude: - tags = soup.find_all(id=id) - for tag in tags: - tag.decompose() - - classes_to_exclude = [ - "elementor-location-header", - "navbar-header", - "nav", - "header-sidebar-wrapper", - "blog-sidebar-wrapper", - "related-posts", - ] - for class_name in classes_to_exclude: - tags = soup.find_all(class_=class_name) - for tag in tags: - tag.decompose() - - content = soup.get_text() - content = clean_string(content) - - cleaned_size = len(content) - if original_size != 0: - logger.info( - f"Cleaned page size: {cleaned_size} characters, down from {original_size} (shrunk: {original_size-cleaned_size} chars, {round((1-(cleaned_size/original_size)) * 100, 2)}%)" # noqa:E501 - ) - - return content - - -def clean_string(text): - """ - This function takes in a string and performs a series of text cleaning operations. - - Args: - text (str): The text to be cleaned. This is expected to be a string. - - Returns: - cleaned_text (str): The cleaned text after all the cleaning operations - have been performed. - """ - # Stripping and reducing multiple spaces to single: - cleaned_text = re.sub(r"\s+", " ", text.strip()) - - # Removing backslashes: - cleaned_text = cleaned_text.replace("\\", "") - - # Replacing hash characters: - cleaned_text = cleaned_text.replace("#", " ") - - # Eliminating consecutive non-alphanumeric characters: - # This regex identifies consecutive non-alphanumeric characters (i.e., not - # a word character [a-zA-Z0-9_] and not a whitespace) in the string - # and replaces each group of such characters with a single occurrence of - # that character. - # For example, "!!! hello !!!" would become "! hello !". - cleaned_text = re.sub(r"([^\w\s])\1*", r"\1", cleaned_text) - - return cleaned_text - - -def is_readable(s): - """ - Heuristic to determine if a string is "readable" (mostly contains printable characters and forms meaningful words) - - :param s: string - :return: True if the string is more than 95% printable. - """ - len_s = len(s) - if len_s == 0: - return False - printable_chars = set(string.printable) - printable_ratio = sum(c in printable_chars for c in s) / len_s - return printable_ratio > 0.95 # 95% of characters are printable - - -def use_pysqlite3(): - """ - Swap std-lib sqlite3 with pysqlite3. - """ - import platform - import sqlite3 - - if platform.system() == "Linux" and sqlite3.sqlite_version_info < (3, 35, 0): - try: - # According to the Chroma team, this patch only works on Linux - import datetime - import subprocess - import sys - - subprocess.check_call( - [sys.executable, "-m", "pip", "install", "pysqlite3-binary", "--quiet", "--disable-pip-version-check"] - ) - - __import__("pysqlite3") - sys.modules["sqlite3"] = sys.modules.pop("pysqlite3") - - # Let the user know what happened. - current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S,%f")[:-3] - print( - f"{current_time} [embedchain] [INFO]", - "Swapped std-lib sqlite3 with pysqlite3 for ChromaDb compatibility.", - f"Your original version was {sqlite3.sqlite_version}.", - ) - except Exception as e: - # Escape all exceptions - current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S,%f")[:-3] - print( - f"{current_time} [embedchain] [ERROR]", - "Failed to swap std-lib sqlite3 with pysqlite3 for ChromaDb compatibility.", - "Error:", - e, - ) - - -def format_source(source: str, limit: int = 20) -> str: - """ - Format a string to only take the first x and last x letters. - This makes it easier to display a URL, keeping familiarity while ensuring a consistent length. - If the string is too short, it is not sliced. - """ - if len(source) > 2 * limit: - return source[:limit] + "..." + source[-limit:] - return source - - -def detect_datatype(source: Any) -> DataType: - """ - Automatically detect the datatype of the given source. - - :param source: the source to base the detection on - :return: data_type string - """ - from urllib.parse import urlparse - - import requests - import yaml - - def is_openapi_yaml(yaml_content): - # currently the following two fields are required in openapi spec yaml config - return "openapi" in yaml_content and "info" in yaml_content - - def is_google_drive_folder(url): - # checks if url is a Google Drive folder url against a regex - regex = r"^drive\.google\.com\/drive\/(?:u\/\d+\/)folders\/([a-zA-Z0-9_-]+)$" - return re.match(regex, url) - - try: - if not isinstance(source, str): - raise ValueError("Source is not a string and thus cannot be a URL.") - url = urlparse(source) - # Check if both scheme and netloc are present. Local file system URIs are acceptable too. - if not all([url.scheme, url.netloc]) and url.scheme != "file": - raise ValueError("Not a valid URL.") - except ValueError: - url = False - - formatted_source = format_source(str(source), 30) - - if url: - YOUTUBE_ALLOWED_NETLOCKS = { - "www.youtube.com", - "m.youtube.com", - "youtu.be", - "youtube.com", - "vid.plus", - "www.youtube-nocookie.com", - } - - if url.netloc in YOUTUBE_ALLOWED_NETLOCKS: - logger.debug(f"Source of `{formatted_source}` detected as `youtube_video`.") - return DataType.YOUTUBE_VIDEO - - if url.netloc in {"notion.so", "notion.site"}: - logger.debug(f"Source of `{formatted_source}` detected as `notion`.") - return DataType.NOTION - - if url.path.endswith(".pdf"): - logger.debug(f"Source of `{formatted_source}` detected as `pdf_file`.") - return DataType.PDF_FILE - - if url.path.endswith(".xml"): - logger.debug(f"Source of `{formatted_source}` detected as `sitemap`.") - return DataType.SITEMAP - - if url.path.endswith(".csv"): - logger.debug(f"Source of `{formatted_source}` detected as `csv`.") - return DataType.CSV - - if url.path.endswith(".mdx") or url.path.endswith(".md"): - logger.debug(f"Source of `{formatted_source}` detected as `mdx`.") - return DataType.MDX - - if url.path.endswith(".docx"): - logger.debug(f"Source of `{formatted_source}` detected as `docx`.") - return DataType.DOCX - - if url.path.endswith( - (".mp3", ".mp4", ".mp2", ".aac", ".wav", ".flac", ".pcm", ".m4a", ".ogg", ".opus", ".webm") - ): - logger.debug(f"Source of `{formatted_source}` detected as `audio`.") - return DataType.AUDIO - - if url.path.endswith(".yaml"): - try: - response = requests.get(source) - response.raise_for_status() - try: - yaml_content = yaml.safe_load(response.text) - except yaml.YAMLError as exc: - logger.error(f"Error parsing YAML: {exc}") - raise TypeError(f"Not a valid data type. Error loading YAML: {exc}") - - if is_openapi_yaml(yaml_content): - logger.debug(f"Source of `{formatted_source}` detected as `openapi`.") - return DataType.OPENAPI - else: - logger.error( - f"Source of `{formatted_source}` does not contain all the required \ - fields of OpenAPI yaml. Check 'https://spec.openapis.org/oas/v3.1.0'" - ) - raise TypeError( - "Not a valid data type. Check 'https://spec.openapis.org/oas/v3.1.0', \ - make sure you have all the required fields in YAML config data" - ) - except requests.exceptions.RequestException as e: - logger.error(f"Error fetching URL {formatted_source}: {e}") - - if url.path.endswith(".json"): - logger.debug(f"Source of `{formatted_source}` detected as `json_file`.") - return DataType.JSON - - if "docs" in url.netloc or ("docs" in url.path and url.scheme != "file"): - # `docs_site` detection via path is not accepted for local filesystem URIs, - # because that would mean all paths that contain `docs` are now doc sites, which is too aggressive. - logger.debug(f"Source of `{formatted_source}` detected as `docs_site`.") - return DataType.DOCS_SITE - - if "github.com" in url.netloc: - logger.debug(f"Source of `{formatted_source}` detected as `github`.") - return DataType.GITHUB - - if is_google_drive_folder(url.netloc + url.path): - logger.debug(f"Source of `{formatted_source}` detected as `google drive folder`.") - return DataType.GOOGLE_DRIVE_FOLDER - - # If none of the above conditions are met, it's a general web page - logger.debug(f"Source of `{formatted_source}` detected as `web_page`.") - return DataType.WEB_PAGE - - elif not isinstance(source, str): - # For datatypes where source is not a string. - - if isinstance(source, tuple) and len(source) == 2 and isinstance(source[0], str) and isinstance(source[1], str): - logger.debug(f"Source of `{formatted_source}` detected as `qna_pair`.") - return DataType.QNA_PAIR - - # Raise an error if it isn't a string and also not a valid non-string type (one of the previous). - # We could stringify it, but it is better to raise an error and let the user decide how they want to do that. - raise TypeError( - "Source is not a string and a valid non-string type could not be detected. If you want to embed it, please stringify it, for instance by using `str(source)` or `(', ').join(source)`." # noqa: E501 - ) - - elif os.path.isfile(source): - # For datatypes that support conventional file references. - # Note: checking for string is not necessary anymore. - - if source.endswith(".docx"): - logger.debug(f"Source of `{formatted_source}` detected as `docx`.") - return DataType.DOCX - - if source.endswith(".csv"): - logger.debug(f"Source of `{formatted_source}` detected as `csv`.") - return DataType.CSV - - if source.endswith(".xml"): - logger.debug(f"Source of `{formatted_source}` detected as `xml`.") - return DataType.XML - - if source.endswith(".mdx") or source.endswith(".md"): - logger.debug(f"Source of `{formatted_source}` detected as `mdx`.") - return DataType.MDX - - if source.endswith(".txt"): - logger.debug(f"Source of `{formatted_source}` detected as `text`.") - return DataType.TEXT_FILE - - if source.endswith(".pdf"): - logger.debug(f"Source of `{formatted_source}` detected as `pdf_file`.") - return DataType.PDF_FILE - - if source.endswith(".yaml"): - with open(source, "r") as file: - yaml_content = yaml.safe_load(file) - if is_openapi_yaml(yaml_content): - logger.debug(f"Source of `{formatted_source}` detected as `openapi`.") - return DataType.OPENAPI - else: - logger.error( - f"Source of `{formatted_source}` does not contain all the required \ - fields of OpenAPI yaml. Check 'https://spec.openapis.org/oas/v3.1.0'" - ) - raise ValueError( - "Invalid YAML data. Check 'https://spec.openapis.org/oas/v3.1.0', \ - make sure to add all the required params" - ) - - if source.endswith(".json"): - logger.debug(f"Source of `{formatted_source}` detected as `json`.") - return DataType.JSON - - if os.path.exists(source) and is_readable(open(source).read()): - logger.debug(f"Source of `{formatted_source}` detected as `text_file`.") - return DataType.TEXT_FILE - - # If the source is a valid file, that's not detectable as a type, an error is raised. - # It does not fall back to text. - raise ValueError( - "Source points to a valid file, but based on the filename, no `data_type` can be detected. Please be aware, that not all data_types allow conventional file references, some require the use of the `file URI scheme`. Please refer to the embedchain documentation (https://docs.embedchain.ai/advanced/data_types#remote-data-types)." # noqa: E501 - ) - - else: - # Source is not a URL. - - # TODO: check if source is gmail query - - # check if the source is valid json string - if is_valid_json_string(source): - logger.debug(f"Source of `{formatted_source}` detected as `json`.") - return DataType.JSON - - # Use text as final fallback. - logger.debug(f"Source of `{formatted_source}` detected as `text`.") - return DataType.TEXT - - -# check if the source is valid json string -def is_valid_json_string(source: str): - try: - _ = json.loads(source) - return True - except json.JSONDecodeError: - return False - - -def validate_config(config_data): - schema = Schema( - { - Optional("app"): { - Optional("config"): { - Optional("id"): str, - Optional("name"): str, - Optional("log_level"): Or("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"), - Optional("collect_metrics"): bool, - Optional("collection_name"): str, - } - }, - Optional("llm"): { - Optional("provider"): Or( - "openai", - "azure_openai", - "anthropic", - "huggingface", - "cohere", - "together", - "gpt4all", - "ollama", - "jina", - "llama2", - "vertexai", - "google", - "aws_bedrock", - "mistralai", - "clarifai", - "vllm", - "groq", - "nvidia", - ), - Optional("config"): { - Optional("model"): str, - Optional("model_name"): str, - Optional("number_documents"): int, - Optional("temperature"): float, - Optional("max_tokens"): int, - Optional("top_p"): Or(float, int), - Optional("stream"): bool, - Optional("online"): bool, - Optional("token_usage"): bool, - Optional("template"): str, - Optional("prompt"): str, - Optional("system_prompt"): str, - Optional("deployment_name"): str, - Optional("where"): dict, - Optional("query_type"): str, - Optional("api_key"): str, - Optional("base_url"): str, - Optional("endpoint"): str, - Optional("model_kwargs"): dict, - Optional("local"): bool, - Optional("base_url"): str, - Optional("default_headers"): dict, - Optional("api_version"): Or(str, datetime.date), - Optional("http_client_proxies"): Or(str, dict), - Optional("http_async_client_proxies"): Or(str, dict), - }, - }, - Optional("vectordb"): { - Optional("provider"): Or( - "chroma", "elasticsearch", "opensearch", "lancedb", "pinecone", "qdrant", "weaviate", "zilliz" - ), - Optional("config"): object, # TODO: add particular config schema for each provider - }, - Optional("embedder"): { - Optional("provider"): Or( - "openai", - "gpt4all", - "huggingface", - "vertexai", - "azure_openai", - "google", - "mistralai", - "clarifai", - "nvidia", - "ollama", - "cohere", - "aws_bedrock", - ), - Optional("config"): { - Optional("model"): Optional(str), - Optional("deployment_name"): Optional(str), - Optional("api_key"): str, - Optional("api_base"): str, - Optional("title"): str, - Optional("task_type"): str, - Optional("vector_dimension"): int, - Optional("base_url"): str, - Optional("endpoint"): str, - Optional("model_kwargs"): dict, - Optional("http_client_proxies"): Or(str, dict), - Optional("http_async_client_proxies"): Or(str, dict), - }, - }, - Optional("embedding_model"): { - Optional("provider"): Or( - "openai", - "gpt4all", - "huggingface", - "vertexai", - "azure_openai", - "google", - "mistralai", - "clarifai", - "nvidia", - "ollama", - "aws_bedrock", - ), - Optional("config"): { - Optional("model"): str, - Optional("deployment_name"): str, - Optional("api_key"): str, - Optional("title"): str, - Optional("task_type"): str, - Optional("vector_dimension"): int, - Optional("base_url"): str, - }, - }, - Optional("chunker"): { - Optional("chunk_size"): int, - Optional("chunk_overlap"): int, - Optional("length_function"): str, - Optional("min_chunk_size"): int, - }, - Optional("cache"): { - Optional("similarity_evaluation"): { - Optional("strategy"): Or("distance", "exact"), - Optional("max_distance"): float, - Optional("positive"): bool, - }, - Optional("config"): { - Optional("similarity_threshold"): float, - Optional("auto_flush"): int, - }, - }, - Optional("memory"): { - Optional("top_k"): int, - }, - } - ) - - return schema.validate(config_data) - - -def chunks(iterable, batch_size=100, desc="Processing chunks"): - """A helper function to break an iterable into chunks of size batch_size.""" - it = iter(iterable) - total_size = len(iterable) - - with tqdm(total=total_size, desc=desc, unit="batch") as pbar: - chunk = tuple(itertools.islice(it, batch_size)) - while chunk: - yield chunk - pbar.update(len(chunk)) - chunk = tuple(itertools.islice(it, batch_size)) diff --git a/embedchain/embedchain/vectordb/__init__.py b/embedchain/embedchain/vectordb/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/embedchain/vectordb/base.py b/embedchain/embedchain/vectordb/base.py deleted file mode 100644 index e65cde01a..000000000 --- a/embedchain/embedchain/vectordb/base.py +++ /dev/null @@ -1,82 +0,0 @@ -from embedchain.config.vector_db.base import BaseVectorDbConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.helpers.json_serializable import JSONSerializable - - -class BaseVectorDB(JSONSerializable): - """Base class for vector database.""" - - def __init__(self, config: BaseVectorDbConfig): - """Initialize the database. Save the config and client as an attribute. - - :param config: Database configuration class instance. - :type config: BaseVectorDbConfig - """ - self.client = self._get_or_create_db() - self.config: BaseVectorDbConfig = config - - def _initialize(self): - """ - This method is needed because `embedder` attribute needs to be set externally before it can be initialized. - - So it's can't be done in __init__ in one step. - """ - raise NotImplementedError - - def _get_or_create_db(self): - """Get or create the database.""" - raise NotImplementedError - - def _get_or_create_collection(self): - """Get or create a named collection.""" - raise NotImplementedError - - def _set_embedder(self, embedder: BaseEmbedder): - """ - The database needs to access the embedder sometimes, with this method you can persistently set it. - - :param embedder: Embedder to be set as the embedder for this database. - :type embedder: BaseEmbedder - """ - self.embedder = embedder - - def get(self): - """Get database embeddings by id.""" - raise NotImplementedError - - def add(self): - """Add to database""" - raise NotImplementedError - - def query(self): - """Query contents from vector database based on vector similarity""" - raise NotImplementedError - - def count(self) -> int: - """ - Count number of documents/chunks embedded in the database. - - :return: number of documents - :rtype: int - """ - raise NotImplementedError - - def reset(self): - """ - Resets the database. Deletes all embeddings irreversibly. - """ - raise NotImplementedError - - def set_collection_name(self, name: str): - """ - Set the name of the collection. A collection is an isolated space for vectors. - - :param name: Name of the collection. - :type name: str - """ - raise NotImplementedError - - def delete(self): - """Delete from database.""" - - raise NotImplementedError diff --git a/embedchain/embedchain/vectordb/chroma.py b/embedchain/embedchain/vectordb/chroma.py deleted file mode 100644 index 746dc149b..000000000 --- a/embedchain/embedchain/vectordb/chroma.py +++ /dev/null @@ -1,290 +0,0 @@ -import logging -from typing import Any, Optional, Union - -from chromadb import Collection, QueryResult -from langchain.docstore.document import Document -from tqdm import tqdm - -from embedchain.config import ChromaDbConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.vectordb.base import BaseVectorDB - -try: - import chromadb - from chromadb.config import Settings - from chromadb.errors import InvalidDimensionException -except RuntimeError: - from embedchain.utils.misc import use_pysqlite3 - - use_pysqlite3() - import chromadb - from chromadb.config import Settings - from chromadb.errors import InvalidDimensionException - - -logger = logging.getLogger(__name__) - - -@register_deserializable -class ChromaDB(BaseVectorDB): - """Vector database using ChromaDB.""" - - def __init__(self, config: Optional[ChromaDbConfig] = None): - """Initialize a new ChromaDB instance - - :param config: Configuration options for Chroma, defaults to None - :type config: Optional[ChromaDbConfig], optional - """ - if config: - self.config = config - else: - self.config = ChromaDbConfig() - - self.settings = Settings(anonymized_telemetry=False) - self.settings.allow_reset = self.config.allow_reset if hasattr(self.config, "allow_reset") else False - self.batch_size = self.config.batch_size - if self.config.chroma_settings: - for key, value in self.config.chroma_settings.items(): - if hasattr(self.settings, key): - setattr(self.settings, key, value) - - if self.config.host and self.config.port: - logger.info(f"Connecting to ChromaDB server: {self.config.host}:{self.config.port}") - self.settings.chroma_server_host = self.config.host - self.settings.chroma_server_http_port = self.config.port - self.settings.chroma_api_impl = "chromadb.api.fastapi.FastAPI" - else: - if self.config.dir is None: - self.config.dir = "db" - - self.settings.persist_directory = self.config.dir - self.settings.is_persistent = True - - self.client = chromadb.Client(self.settings) - super().__init__(config=self.config) - - def _initialize(self): - """ - This method is needed because `embedder` attribute needs to be set externally before it can be initialized. - """ - if not self.embedder: - raise ValueError( - "Embedder not set. Please set an embedder with `_set_embedder()` function before initialization." - ) - self._get_or_create_collection(self.config.collection_name) - - def _get_or_create_db(self): - """Called during initialization""" - return self.client - - @staticmethod - def _generate_where_clause(where: dict[str, any]) -> dict[str, any]: - # If only one filter is supplied, return it as is - # (no need to wrap in $and based on chroma docs) - if where is None: - return {} - if len(where.keys()) <= 1: - return where - where_filters = [] - for k, v in where.items(): - if isinstance(v, str): - where_filters.append({k: v}) - return {"$and": where_filters} - - def _get_or_create_collection(self, name: str) -> Collection: - """ - Get or create a named collection. - - :param name: Name of the collection - :type name: str - :raises ValueError: No embedder configured. - :return: Created collection - :rtype: Collection - """ - if not hasattr(self, "embedder") or not self.embedder: - raise ValueError("Cannot create a Chroma database collection without an embedder.") - self.collection = self.client.get_or_create_collection( - name=name, - embedding_function=self.embedder.embedding_fn, - ) - return self.collection - - def get(self, ids: Optional[list[str]] = None, where: Optional[dict[str, any]] = None, limit: Optional[int] = None): - """ - Get existing doc ids present in vector database - - :param ids: list of doc ids to check for existence - :type ids: list[str] - :param where: Optional. to filter data - :type where: dict[str, Any] - :param limit: Optional. maximum number of documents - :type limit: Optional[int] - :return: Existing documents. - :rtype: list[str] - """ - args = {} - if ids: - args["ids"] = ids - if where: - args["where"] = self._generate_where_clause(where) - if limit: - args["limit"] = limit - return self.collection.get(**args) - - def add( - self, - documents: list[str], - metadatas: list[object], - ids: list[str], - **kwargs: Optional[dict[str, Any]], - ) -> Any: - """ - Add vectors to chroma database - - :param documents: Documents - :type documents: list[str] - :param metadatas: Metadatas - :type metadatas: list[object] - :param ids: ids - :type ids: list[str] - """ - size = len(documents) - if len(documents) != size or len(metadatas) != size or len(ids) != size: - raise ValueError( - "Cannot add documents to chromadb with inconsistent sizes. Documents size: {}, Metadata size: {}," - " Ids size: {}".format(len(documents), len(metadatas), len(ids)) - ) - - for i in tqdm(range(0, len(documents), self.batch_size), desc="Inserting batches in chromadb"): - self.collection.add( - documents=documents[i : i + self.batch_size], - metadatas=metadatas[i : i + self.batch_size], - ids=ids[i : i + self.batch_size], - ) - self.config - - @staticmethod - def _format_result(results: QueryResult) -> list[tuple[Document, float]]: - """ - Format Chroma results - - :param results: ChromaDB query results to format. - :type results: QueryResult - :return: Formatted results - :rtype: list[tuple[Document, float]] - """ - return [ - (Document(page_content=result[0], metadata=result[1] or {}), result[2]) - for result in zip( - results["documents"][0], - results["metadatas"][0], - results["distances"][0], - ) - ] - - def query( - self, - input_query: str, - n_results: int, - where: Optional[dict[str, any]] = None, - raw_filter: Optional[dict[str, any]] = None, - citations: bool = False, - **kwargs: Optional[dict[str, any]], - ) -> Union[list[tuple[str, dict]], list[str]]: - """ - Query contents from vector database based on vector similarity - - :param input_query: query string - :type input_query: str - :param n_results: no of similar documents to fetch from database - :type n_results: int - :param where: to filter data - :type where: dict[str, Any] - :param raw_filter: Raw filter to apply - :type raw_filter: dict[str, Any] - :param citations: we use citations boolean param to return context along with the answer. - :type citations: bool, default is False. - :raises InvalidDimensionException: Dimensions do not match. - :return: The content of the document that matched your query, - along with url of the source and doc_id (if citations flag is true) - :rtype: list[str], if citations=False, otherwise list[tuple[str, str, str]] - """ - if where and raw_filter: - raise ValueError("Both `where` and `raw_filter` cannot be used together.") - - where_clause = None - if raw_filter: - where_clause = raw_filter - if where: - where_clause = self._generate_where_clause(where) - try: - result = self.collection.query( - query_texts=[ - input_query, - ], - n_results=n_results, - where=where_clause, - ) - except InvalidDimensionException as e: - raise InvalidDimensionException( - e.message() - + ". This is commonly a side-effect when an embedding function, different from the one used to add the" - " embeddings, is used to retrieve an embedding from the database." - ) from None - results_formatted = self._format_result(result) - contexts = [] - for result in results_formatted: - context = result[0].page_content - if citations: - metadata = result[0].metadata - metadata["score"] = result[1] - contexts.append((context, metadata)) - else: - contexts.append(context) - return contexts - - def set_collection_name(self, name: str): - """ - Set the name of the collection. A collection is an isolated space for vectors. - - :param name: Name of the collection. - :type name: str - """ - if not isinstance(name, str): - raise TypeError("Collection name must be a string") - self.config.collection_name = name - self._get_or_create_collection(self.config.collection_name) - - def count(self) -> int: - """ - Count number of documents/chunks embedded in the database. - - :return: number of documents - :rtype: int - """ - return self.collection.count() - - def delete(self, where): - return self.collection.delete(where=self._generate_where_clause(where)) - - def reset(self): - """ - Resets the database. Deletes all embeddings irreversibly. - """ - # Delete all data from the collection - try: - self.client.delete_collection(self.config.collection_name) - except ValueError: - raise ValueError( - "For safety reasons, resetting is disabled. " - "Please enable it by setting `allow_reset=True` in your ChromaDbConfig" - ) from None - # Recreate - self._get_or_create_collection(self.config.collection_name) - - # Todo: Automatically recreating a collection with the same name cannot be the best way to handle a reset. - # A downside of this implementation is, if you have two instances, - # the other instance will not get the updated `self.collection` attribute. - # A better way would be to create the collection if it is called again after being reset. - # That means, checking if collection exists in the db-consuming methods, and creating it if it doesn't. - # That's an extra steps for all uses, just to satisfy a niche use case in a niche method. For now, this will do. diff --git a/embedchain/embedchain/vectordb/elasticsearch.py b/embedchain/embedchain/vectordb/elasticsearch.py deleted file mode 100644 index 12b871762..000000000 --- a/embedchain/embedchain/vectordb/elasticsearch.py +++ /dev/null @@ -1,269 +0,0 @@ -import logging -from typing import Any, Optional, Union - -try: - from elasticsearch import Elasticsearch - from elasticsearch.helpers import bulk -except ImportError: - raise ImportError( - "Elasticsearch requires extra dependencies. Install with `pip install --upgrade embedchain[elasticsearch]`" - ) from None - -from embedchain.config import ElasticsearchDBConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.utils.misc import chunks -from embedchain.vectordb.base import BaseVectorDB - -logger = logging.getLogger(__name__) - - -@register_deserializable -class ElasticsearchDB(BaseVectorDB): - """ - Elasticsearch as vector database - """ - - def __init__( - self, - config: Optional[ElasticsearchDBConfig] = None, - es_config: Optional[ElasticsearchDBConfig] = None, # Backwards compatibility - ): - """Elasticsearch as vector database. - - :param config: Elasticsearch database config, defaults to None - :type config: ElasticsearchDBConfig, optional - :param es_config: `es_config` is supported as an alias for `config` (for backwards compatibility), - defaults to None - :type es_config: ElasticsearchDBConfig, optional - :raises ValueError: No config provided - """ - if config is None and es_config is None: - self.config = ElasticsearchDBConfig() - else: - if not isinstance(config, ElasticsearchDBConfig): - raise TypeError( - "config is not a `ElasticsearchDBConfig` instance. " - "Please make sure the type is right and that you are passing an instance." - ) - self.config = config or es_config - if self.config.ES_URL: - self.client = Elasticsearch(self.config.ES_URL, **self.config.ES_EXTRA_PARAMS) - elif self.config.CLOUD_ID: - self.client = Elasticsearch(cloud_id=self.config.CLOUD_ID, **self.config.ES_EXTRA_PARAMS) - else: - raise ValueError( - "Something is wrong with your config. Please check again - `https://docs.embedchain.ai/components/vector-databases#elasticsearch`" # noqa: E501 - ) - - self.batch_size = self.config.batch_size - # Call parent init here because embedder is needed - super().__init__(config=self.config) - - def _initialize(self): - """ - This method is needed because `embedder` attribute needs to be set externally before it can be initialized. - """ - logger.info(self.client.info()) - index_settings = { - "mappings": { - "properties": { - "text": {"type": "text"}, - "embeddings": {"type": "dense_vector", "index": False, "dims": self.embedder.vector_dimension}, - } - } - } - es_index = self._get_index() - if not self.client.indices.exists(index=es_index): - # create index if not exist - print("Creating index", es_index, index_settings) - self.client.indices.create(index=es_index, body=index_settings) - - def _get_or_create_db(self): - """Called during initialization""" - return self.client - - def _get_or_create_collection(self, name): - """Note: nothing to return here. Discuss later""" - - def get(self, ids: Optional[list[str]] = None, where: Optional[dict[str, any]] = None, limit: Optional[int] = None): - """ - Get existing doc ids present in vector database - - :param ids: _list of doc ids to check for existence - :type ids: list[str] - :param where: to filter data - :type where: dict[str, any] - :return: ids - :rtype: Set[str] - """ - if ids: - query = {"bool": {"must": [{"ids": {"values": ids}}]}} - else: - query = {"bool": {"must": []}} - - if where: - for key, value in where.items(): - query["bool"]["must"].append({"term": {f"metadata.{key}.keyword": value}}) - - response = self.client.search(index=self._get_index(), query=query, _source=True, size=limit) - docs = response["hits"]["hits"] - ids = [doc["_id"] for doc in docs] - doc_ids = [doc["_source"]["metadata"]["doc_id"] for doc in docs] - - # Result is modified for compatibility with other vector databases - # TODO: Add method in vector database to return result in a standard format - result = {"ids": ids, "metadatas": []} - - for doc_id in doc_ids: - result["metadatas"].append({"doc_id": doc_id}) - - return result - - def add( - self, - documents: list[str], - metadatas: list[object], - ids: list[str], - **kwargs: Optional[dict[str, any]], - ) -> Any: - """ - add data in vector database - :param documents: list of texts to add - :type documents: list[str] - :param metadatas: list of metadata associated with docs - :type metadatas: list[object] - :param ids: ids of docs - :type ids: list[str] - """ - - embeddings = self.embedder.embedding_fn(documents) - - for chunk in chunks( - list(zip(ids, documents, metadatas, embeddings)), - self.batch_size, - desc="Inserting batches in elasticsearch", - ): # noqa: E501 - ids, docs, metadatas, embeddings = [], [], [], [] - for id, text, metadata, embedding in chunk: - ids.append(id) - docs.append(text) - metadatas.append(metadata) - embeddings.append(embedding) - - batch_docs = [] - for id, text, metadata, embedding in zip(ids, docs, metadatas, embeddings): - batch_docs.append( - { - "_index": self._get_index(), - "_id": id, - "_source": {"text": text, "metadata": metadata, "embeddings": embedding}, - } - ) - bulk(self.client, batch_docs, **kwargs) - self.client.indices.refresh(index=self._get_index()) - - def query( - self, - input_query: str, - n_results: int, - where: dict[str, any], - citations: bool = False, - **kwargs: Optional[dict[str, Any]], - ) -> Union[list[tuple[str, dict]], list[str]]: - """ - query contents from vector database based on vector similarity - - :param input_query: query string - :type input_query: str - :param n_results: no of similar documents to fetch from database - :type n_results: int - :param where: Optional. to filter data - :type where: dict[str, any] - :return: The context of the document that matched your query, url of the source, doc_id - :param citations: we use citations boolean param to return context along with the answer. - :type citations: bool, default is False. - :return: The content of the document that matched your query, - along with url of the source and doc_id (if citations flag is true) - :rtype: list[str], if citations=False, otherwise list[tuple[str, str, str]] - """ - input_query_vector = self.embedder.embedding_fn([input_query]) - query_vector = input_query_vector[0] - - # `https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-script-score-query.html` - query = { - "script_score": { - "query": {"bool": {"must": [{"exists": {"field": "text"}}]}}, - "script": { - "source": "cosineSimilarity(params.input_query_vector, 'embeddings') + 1.0", - "params": {"input_query_vector": query_vector}, - }, - } - } - - if where: - for key, value in where.items(): - query["script_score"]["query"]["bool"]["must"].append({"term": {f"metadata.{key}.keyword": value}}) - - _source = ["text", "metadata"] - response = self.client.search(index=self._get_index(), query=query, _source=_source, size=n_results) - docs = response["hits"]["hits"] - contexts = [] - for doc in docs: - context = doc["_source"]["text"] - if citations: - metadata = doc["_source"]["metadata"] - metadata["score"] = doc["_score"] - contexts.append(tuple((context, metadata))) - else: - contexts.append(context) - return contexts - - def set_collection_name(self, name: str): - """ - Set the name of the collection. A collection is an isolated space for vectors. - - :param name: Name of the collection. - :type name: str - """ - if not isinstance(name, str): - raise TypeError("Collection name must be a string") - self.config.collection_name = name - - def count(self) -> int: - """ - Count number of documents/chunks embedded in the database. - - :return: number of documents - :rtype: int - """ - query = {"match_all": {}} - response = self.client.count(index=self._get_index(), query=query) - doc_count = response["count"] - return doc_count - - def reset(self): - """ - Resets the database. Deletes all embeddings irreversibly. - """ - # Delete all data from the database - if self.client.indices.exists(index=self._get_index()): - # delete index in Es - self.client.indices.delete(index=self._get_index()) - - def _get_index(self) -> str: - """Get the Elasticsearch index for a collection - - :return: Elasticsearch index - :rtype: str - """ - # NOTE: The method is preferred to an attribute, because if collection name changes, - # it's always up-to-date. - return f"{self.config.collection_name}_{self.embedder.vector_dimension}".lower() - - def delete(self, where): - """Delete documents from the database.""" - query = {"query": {"bool": {"must": []}}} - for key, value in where.items(): - query["query"]["bool"]["must"].append({"term": {f"metadata.{key}.keyword": value}}) - self.client.delete_by_query(index=self._get_index(), body=query) - self.client.indices.refresh(index=self._get_index()) diff --git a/embedchain/embedchain/vectordb/lancedb.py b/embedchain/embedchain/vectordb/lancedb.py deleted file mode 100644 index d3d4b6898..000000000 --- a/embedchain/embedchain/vectordb/lancedb.py +++ /dev/null @@ -1,305 +0,0 @@ -from typing import Any, Dict, List, Optional, Union - -import pyarrow as pa - -try: - import lancedb -except ImportError: - raise ImportError('LanceDB is required. Install with pip install "embedchain[lancedb]"') from None - -from embedchain.config.vector_db.lancedb import LanceDBConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.vectordb.base import BaseVectorDB - - -@register_deserializable -class LanceDB(BaseVectorDB): - """ - LanceDB as vector database - """ - - def __init__( - self, - config: Optional[LanceDBConfig] = None, - ): - """LanceDB as vector database. - - :param config: LanceDB database config, defaults to None - :type config: LanceDBConfig, optional - """ - if config: - self.config = config - else: - self.config = LanceDBConfig() - - self.client = lancedb.connect(self.config.dir or "~/.lancedb") - self.embedder_check = True - - super().__init__(config=self.config) - - def _initialize(self): - """ - This method is needed because `embedder` attribute needs to be set externally before it can be initialized. - """ - if not self.embedder: - raise ValueError( - "Embedder not set. Please set an embedder with `_set_embedder()` function before initialization." - ) - else: - # check embedder function is working or not - try: - self.embedder.embedding_fn("Hello LanceDB") - except Exception: - self.embedder_check = False - - self._get_or_create_collection(self.config.collection_name) - - def _get_or_create_db(self): - """ - Called during initialization - """ - return self.client - - def _generate_where_clause(self, where: Dict[str, any]) -> str: - """ - This method generate where clause using dictionary containing attributes and their values - """ - - where_filters = "" - - if len(list(where.keys())) == 1: - where_filters = f"{list(where.keys())[0]} = {list(where.values())[0]}" - return where_filters - - where_items = list(where.items()) - where_count = len(where_items) - - for i, (key, value) in enumerate(where_items, start=1): - condition = f"{key} = {value} AND " - where_filters += condition - - if i == where_count: - condition = f"{key} = {value}" - where_filters += condition - - return where_filters - - def _get_or_create_collection(self, table_name: str, reset=False): - """ - Get or create a named collection. - - :param name: Name of the collection - :type name: str - :return: Created collection - :rtype: Collection - """ - if not self.embedder_check: - schema = pa.schema( - [ - pa.field("doc", pa.string()), - pa.field("metadata", pa.string()), - pa.field("id", pa.string()), - ] - ) - - else: - schema = pa.schema( - [ - pa.field("vector", pa.list_(pa.float32(), list_size=self.embedder.vector_dimension)), - pa.field("doc", pa.string()), - pa.field("metadata", pa.string()), - pa.field("id", pa.string()), - ] - ) - - if not reset: - if table_name not in self.client.table_names(): - self.collection = self.client.create_table(table_name, schema=schema) - - else: - self.client.drop_table(table_name) - self.collection = self.client.create_table(table_name, schema=schema) - - self.collection = self.client[table_name] - - return self.collection - - def get(self, ids: Optional[List[str]] = None, where: Optional[Dict[str, any]] = None, limit: Optional[int] = None): - """ - Get existing doc ids present in vector database - - :param ids: list of doc ids to check for existence - :type ids: List[str] - :param where: Optional. to filter data - :type where: Dict[str, Any] - :param limit: Optional. maximum number of documents - :type limit: Optional[int] - :return: Existing documents. - :rtype: List[str] - """ - if limit is not None: - max_limit = limit - else: - max_limit = 3 - results = {"ids": [], "metadatas": []} - - where_clause = {} - if where: - where_clause = self._generate_where_clause(where) - - if ids is not None: - records = ( - self.collection.to_lance().scanner(filter=f"id IN {tuple(ids)}", columns=["id"]).to_table().to_pydict() - ) - for id in records["id"]: - if where is not None: - result = ( - self.collection.search(query=id, vector_column_name="id") - .where(where_clause) - .limit(max_limit) - .to_list() - ) - else: - result = self.collection.search(query=id, vector_column_name="id").limit(max_limit).to_list() - results["ids"] = [r["id"] for r in result] - results["metadatas"] = [r["metadata"] for r in result] - - return results - - def add( - self, - documents: List[str], - metadatas: List[object], - ids: List[str], - ) -> Any: - """ - Add vectors to lancedb database - - :param documents: Documents - :type documents: List[str] - :param metadatas: Metadatas - :type metadatas: List[object] - :param ids: ids - :type ids: List[str] - """ - data = [] - to_ingest = list(zip(documents, metadatas, ids)) - - if not self.embedder_check: - for doc, meta, id in to_ingest: - temp = {} - temp["doc"] = doc - temp["metadata"] = str(meta) - temp["id"] = id - data.append(temp) - else: - for doc, meta, id in to_ingest: - temp = {} - temp["doc"] = doc - temp["vector"] = self.embedder.embedding_fn([doc])[0] - temp["metadata"] = str(meta) - temp["id"] = id - data.append(temp) - - self.collection.add(data=data) - - def _format_result(self, results) -> list: - """ - Format LanceDB results - - :param results: LanceDB query results to format. - :type results: QueryResult - :return: Formatted results - :rtype: list[tuple[Document, float]] - """ - return results.tolist() - - def query( - self, - input_query: str, - n_results: int = 3, - where: Optional[dict[str, any]] = None, - raw_filter: Optional[dict[str, any]] = None, - citations: bool = False, - **kwargs: Optional[dict[str, any]], - ) -> Union[list[tuple[str, dict]], list[str]]: - """ - Query contents from vector database based on vector similarity - - :param input_query: query string - :type input_query: str - :param n_results: no of similar documents to fetch from database - :type n_results: int - :param where: to filter data - :type where: dict[str, Any] - :param raw_filter: Raw filter to apply - :type raw_filter: dict[str, Any] - :param citations: we use citations boolean param to return context along with the answer. - :type citations: bool, default is False. - :raises InvalidDimensionException: Dimensions do not match. - :return: The content of the document that matched your query, - along with url of the source and doc_id (if citations flag is true) - :rtype: list[str], if citations=False, otherwise list[tuple[str, str, str]] - """ - if where and raw_filter: - raise ValueError("Both `where` and `raw_filter` cannot be used together.") - try: - query_embedding = self.embedder.embedding_fn(input_query)[0] - result = self.collection.search(query_embedding).limit(n_results).to_list() - except Exception as e: - e.message() - - results_formatted = result - - contexts = [] - for result in results_formatted: - if citations: - metadata = result["metadata"] - contexts.append((result["doc"], metadata)) - else: - contexts.append(result["doc"]) - return contexts - - def set_collection_name(self, name: str): - """ - Set the name of the collection. A collection is an isolated space for vectors. - - :param name: Name of the collection. - :type name: str - """ - if not isinstance(name, str): - raise TypeError("Collection name must be a string") - self.config.collection_name = name - self._get_or_create_collection(self.config.collection_name) - - def count(self) -> int: - """ - Count number of documents/chunks embedded in the database. - - :return: number of documents - :rtype: int - """ - return self.collection.count_rows() - - def delete(self, where): - return self.collection.delete(where=where) - - def reset(self): - """ - Resets the database. Deletes all embeddings irreversibly. - """ - # Delete all data from the collection and recreate collection - if self.config.allow_reset: - try: - self._get_or_create_collection(self.config.collection_name, reset=True) - except ValueError: - raise ValueError( - "For safety reasons, resetting is disabled. " - "Please enable it by setting `allow_reset=True` in your LanceDbConfig" - ) from None - # Recreate - else: - print( - "For safety reasons, resetting is disabled. " - "Please enable it by setting `allow_reset=True` in your LanceDbConfig" - ) diff --git a/embedchain/embedchain/vectordb/opensearch.py b/embedchain/embedchain/vectordb/opensearch.py deleted file mode 100644 index accec4324..000000000 --- a/embedchain/embedchain/vectordb/opensearch.py +++ /dev/null @@ -1,253 +0,0 @@ -import logging -import time -from typing import Any, Optional, Union - -from tqdm import tqdm - -try: - from opensearchpy import OpenSearch - from opensearchpy.helpers import bulk -except ImportError: - raise ImportError( - "OpenSearch requires extra dependencies. Install with `pip install --upgrade embedchain[opensearch]`" - ) from None - -from langchain_community.embeddings.openai import OpenAIEmbeddings -from langchain_community.vectorstores import OpenSearchVectorSearch - -from embedchain.config import OpenSearchDBConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.vectordb.base import BaseVectorDB - -logger = logging.getLogger(__name__) - - -@register_deserializable -class OpenSearchDB(BaseVectorDB): - """ - OpenSearch as vector database - """ - - def __init__(self, config: OpenSearchDBConfig): - """OpenSearch as vector database. - - :param config: OpenSearch domain config - :type config: OpenSearchDBConfig - """ - if config is None: - raise ValueError("OpenSearchDBConfig is required") - self.config = config - self.batch_size = self.config.batch_size - self.client = OpenSearch( - hosts=[self.config.opensearch_url], - http_auth=self.config.http_auth, - **self.config.extra_params, - ) - info = self.client.info() - logger.info(f"Connected to {info['version']['distribution']}. Version: {info['version']['number']}") - # Remove auth credentials from config after successful connection - super().__init__(config=self.config) - - def _initialize(self): - logger.info(self.client.info()) - index_name = self._get_index() - if self.client.indices.exists(index=index_name): - print(f"Index '{index_name}' already exists.") - return - - index_body = { - "settings": {"knn": True}, - "mappings": { - "properties": { - "text": {"type": "text"}, - "embeddings": { - "type": "knn_vector", - "index": False, - "dimension": self.config.vector_dimension, - }, - } - }, - } - self.client.indices.create(index_name, body=index_body) - print(self.client.indices.get(index_name)) - - def _get_or_create_db(self): - """Called during initialization""" - return self.client - - def _get_or_create_collection(self, name): - """Note: nothing to return here. Discuss later""" - - def get( - self, ids: Optional[list[str]] = None, where: Optional[dict[str, any]] = None, limit: Optional[int] = None - ) -> set[str]: - """ - Get existing doc ids present in vector database - - :param ids: _list of doc ids to check for existence - :type ids: list[str] - :param where: to filter data - :type where: dict[str, any] - :return: ids - :type: set[str] - """ - query = {} - if ids: - query["query"] = {"bool": {"must": [{"ids": {"values": ids}}]}} - else: - query["query"] = {"bool": {"must": []}} - - if where: - for key, value in where.items(): - query["query"]["bool"]["must"].append({"term": {f"metadata.{key}.keyword": value}}) - - # OpenSearch syntax is different from Elasticsearch - response = self.client.search(index=self._get_index(), body=query, _source=True, size=limit) - docs = response["hits"]["hits"] - ids = [doc["_id"] for doc in docs] - doc_ids = [doc["_source"]["metadata"]["doc_id"] for doc in docs] - - # Result is modified for compatibility with other vector databases - # TODO: Add method in vector database to return result in a standard format - result = {"ids": ids, "metadatas": []} - - for doc_id in doc_ids: - result["metadatas"].append({"doc_id": doc_id}) - return result - - def add(self, documents: list[str], metadatas: list[object], ids: list[str], **kwargs: Optional[dict[str, any]]): - """Adds documents to the opensearch index""" - - embeddings = self.embedder.embedding_fn(documents) - for batch_start in tqdm(range(0, len(documents), self.batch_size), desc="Inserting batches in opensearch"): - batch_end = batch_start + self.batch_size - batch_documents = documents[batch_start:batch_end] - batch_embeddings = embeddings[batch_start:batch_end] - - # Create document entries for bulk upload - batch_entries = [ - { - "_index": self._get_index(), - "_id": doc_id, - "_source": {"text": text, "metadata": metadata, "embeddings": embedding}, - } - for doc_id, text, metadata, embedding in zip( - ids[batch_start:batch_end], batch_documents, metadatas[batch_start:batch_end], batch_embeddings - ) - ] - - # Perform bulk operation - bulk(self.client, batch_entries, **kwargs) - self.client.indices.refresh(index=self._get_index()) - - # Sleep to avoid rate limiting - time.sleep(0.1) - - def query( - self, - input_query: str, - n_results: int, - where: dict[str, any], - citations: bool = False, - **kwargs: Optional[dict[str, Any]], - ) -> Union[list[tuple[str, dict]], list[str]]: - """ - query contents from vector database based on vector similarity - - :param input_query: query string - :type input_query: str - :param n_results: no of similar documents to fetch from database - :type n_results: int - :param where: Optional. to filter data - :type where: dict[str, any] - :param citations: we use citations boolean param to return context along with the answer. - :type citations: bool, default is False. - :return: The content of the document that matched your query, - along with url of the source and doc_id (if citations flag is true) - :rtype: list[str], if citations=False, otherwise list[tuple[str, str, str]] - """ - embeddings = OpenAIEmbeddings() - docsearch = OpenSearchVectorSearch( - index_name=self._get_index(), - embedding_function=embeddings, - opensearch_url=f"{self.config.opensearch_url}", - http_auth=self.config.http_auth, - use_ssl=hasattr(self.config, "use_ssl") and self.config.use_ssl, - verify_certs=hasattr(self.config, "verify_certs") and self.config.verify_certs, - ) - - pre_filter = {"match_all": {}} # default - if len(where) > 0: - pre_filter = {"bool": {"must": []}} - for key, value in where.items(): - pre_filter["bool"]["must"].append({"term": {f"metadata.{key}.keyword": value}}) - - docs = docsearch.similarity_search_with_score( - input_query, - search_type="script_scoring", - space_type="cosinesimil", - vector_field="embeddings", - text_field="text", - metadata_field="metadata", - pre_filter=pre_filter, - k=n_results, - **kwargs, - ) - - contexts = [] - for doc, score in docs: - context = doc.page_content - if citations: - metadata = doc.metadata - metadata["score"] = score - contexts.append(tuple((context, metadata))) - else: - contexts.append(context) - return contexts - - def set_collection_name(self, name: str): - """ - Set the name of the collection. A collection is an isolated space for vectors. - - :param name: Name of the collection. - :type name: str - """ - if not isinstance(name, str): - raise TypeError("Collection name must be a string") - self.config.collection_name = name - - def count(self) -> int: - """ - Count number of documents/chunks embedded in the database. - - :return: number of documents - :rtype: int - """ - query = {"query": {"match_all": {}}} - response = self.client.count(index=self._get_index(), body=query) - doc_count = response["count"] - return doc_count - - def reset(self): - """ - Resets the database. Deletes all embeddings irreversibly. - """ - # Delete all data from the database - if self.client.indices.exists(index=self._get_index()): - # delete index in ES - self.client.indices.delete(index=self._get_index()) - - def delete(self, where): - """Deletes a document from the OpenSearch index""" - query = {"query": {"bool": {"must": []}}} - for key, value in where.items(): - query["query"]["bool"]["must"].append({"term": {f"metadata.{key}.keyword": value}}) - self.client.delete_by_query(index=self._get_index(), body=query) - - def _get_index(self) -> str: - """Get the OpenSearch index for a collection - - :return: OpenSearch index - :rtype: str - """ - return self.config.collection_name diff --git a/embedchain/embedchain/vectordb/pinecone.py b/embedchain/embedchain/vectordb/pinecone.py deleted file mode 100644 index 3c0520ce3..000000000 --- a/embedchain/embedchain/vectordb/pinecone.py +++ /dev/null @@ -1,252 +0,0 @@ -import logging -import os -from typing import Optional, Union - -try: - import pinecone -except ImportError: - raise ImportError( - "Pinecone requires extra dependencies. Install with `pip install pinecone-text pinecone-client`" - ) from None - -from pinecone_text.sparse import BM25Encoder - -from embedchain.config.vector_db.pinecone import PineconeDBConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.utils.misc import chunks -from embedchain.vectordb.base import BaseVectorDB - -logger = logging.getLogger(__name__) - - -@register_deserializable -class PineconeDB(BaseVectorDB): - """ - Pinecone as vector database - """ - - def __init__( - self, - config: Optional[PineconeDBConfig] = None, - ): - """Pinecone as vector database. - - :param config: Pinecone database config, defaults to None - :type config: PineconeDBConfig, optional - :raises ValueError: No config provided - """ - if config is None: - self.config = PineconeDBConfig() - else: - if not isinstance(config, PineconeDBConfig): - raise TypeError( - "config is not a `PineconeDBConfig` instance. " - "Please make sure the type is right and that you are passing an instance." - ) - self.config = config - self._setup_pinecone_index() - - # Setup BM25Encoder if sparse vectors are to be used - self.bm25_encoder = None - self.batch_size = self.config.batch_size - if self.config.hybrid_search: - logger.info("Initializing BM25Encoder for sparse vectors..") - self.bm25_encoder = self.config.bm25_encoder if self.config.bm25_encoder else BM25Encoder.default() - - # Call parent init here because embedder is needed - super().__init__(config=self.config) - - def _initialize(self): - """ - This method is needed because `embedder` attribute needs to be set externally before it can be initialized. - """ - if not self.embedder: - raise ValueError("Embedder not set. Please set an embedder with `set_embedder` before initialization.") - - def _setup_pinecone_index(self): - """ - Loads the Pinecone index or creates it if not present. - """ - api_key = self.config.api_key or os.environ.get("PINECONE_API_KEY") - if not api_key: - raise ValueError("Please set the PINECONE_API_KEY environment variable or pass it in config.") - self.client = pinecone.Pinecone(api_key=api_key, **self.config.extra_params) - indexes = self.client.list_indexes().names() - if indexes is None or self.config.index_name not in indexes: - if self.config.pod_config: - spec = pinecone.PodSpec(**self.config.pod_config) - elif self.config.serverless_config: - spec = pinecone.ServerlessSpec(**self.config.serverless_config) - else: - raise ValueError("No pod_config or serverless_config found.") - - self.client.create_index( - name=self.config.index_name, - metric=self.config.metric, - dimension=self.config.vector_dimension, - spec=spec, - ) - self.pinecone_index = self.client.Index(self.config.index_name) - - def get(self, ids: Optional[list[str]] = None, where: Optional[dict[str, any]] = None, limit: Optional[int] = None): - """ - Get existing doc ids present in vector database - - :param ids: _list of doc ids to check for existence - :type ids: list[str] - :param where: to filter data - :type where: dict[str, any] - :return: ids - :rtype: Set[str] - """ - existing_ids = list() - metadatas = [] - - if ids is not None: - for i in range(0, len(ids), self.batch_size): - result = self.pinecone_index.fetch(ids=ids[i : i + self.batch_size]) - vectors = result.get("vectors") - batch_existing_ids = list(vectors.keys()) - existing_ids.extend(batch_existing_ids) - metadatas.extend([vectors.get(ids).get("metadata") for ids in batch_existing_ids]) - return {"ids": existing_ids, "metadatas": metadatas} - - def add( - self, - documents: list[str], - metadatas: list[object], - ids: list[str], - **kwargs: Optional[dict[str, any]], - ): - """add data in vector database - - :param documents: list of texts to add - :type documents: list[str] - :param metadatas: list of metadata associated with docs - :type metadatas: list[object] - :param ids: ids of docs - :type ids: list[str] - """ - docs = [] - embeddings = self.embedder.embedding_fn(documents) - for id, text, metadata, embedding in zip(ids, documents, metadatas, embeddings): - # Insert sparse vectors as well if the user wants to do the hybrid search - sparse_vector_dict = ( - {"sparse_values": self.bm25_encoder.encode_documents(text)} if self.bm25_encoder else {} - ) - docs.append( - { - "id": id, - "values": embedding, - "metadata": {**metadata, "text": text}, - **sparse_vector_dict, - }, - ) - - for chunk in chunks(docs, self.batch_size, desc="Adding chunks in batches"): - self.pinecone_index.upsert(chunk, **kwargs) - - def query( - self, - input_query: str, - n_results: int, - where: Optional[dict[str, any]] = None, - raw_filter: Optional[dict[str, any]] = None, - citations: bool = False, - app_id: Optional[str] = None, - **kwargs: Optional[dict[str, any]], - ) -> Union[list[tuple[str, dict]], list[str]]: - """ - Query contents from vector database based on vector similarity. - - Args: - input_query (str): query string. - n_results (int): Number of similar documents to fetch from the database. - where (dict[str, any], optional): Filter criteria for the search. - raw_filter (dict[str, any], optional): Advanced raw filter criteria for the search. - citations (bool, optional): Flag to return context along with metadata. Defaults to False. - app_id (str, optional): Application ID to be passed to Pinecone. - - Returns: - Union[list[tuple[str, dict]], list[str]]: List of document contexts, optionally with metadata. - """ - query_filter = raw_filter if raw_filter is not None else self._generate_filter(where) - if app_id: - query_filter["app_id"] = {"$eq": app_id} - - query_vector = self.embedder.embedding_fn([input_query])[0] - params = { - "vector": query_vector, - "filter": query_filter, - "top_k": n_results, - "include_metadata": True, - **kwargs, - } - - if self.bm25_encoder: - sparse_query_vector = self.bm25_encoder.encode_queries(input_query) - params["sparse_vector"] = sparse_query_vector - - data = self.pinecone_index.query(**params) - return [ - (metadata.get("text"), {**metadata, "score": doc.get("score")}) if citations else metadata.get("text") - for doc in data.get("matches", []) - for metadata in [doc.get("metadata", {})] - ] - - def set_collection_name(self, name: str): - """ - Set the name of the collection. A collection is an isolated space for vectors. - - :param name: Name of the collection. - :type name: str - """ - if not isinstance(name, str): - raise TypeError("Collection name must be a string") - self.config.collection_name = name - - def count(self) -> int: - """ - Count number of documents/chunks embedded in the database. - - :return: number of documents - :rtype: int - """ - data = self.pinecone_index.describe_index_stats() - return data["total_vector_count"] - - def _get_or_create_db(self): - """Called during initialization""" - return self.client - - def reset(self): - """ - Resets the database. Deletes all embeddings irreversibly. - """ - # Delete all data from the database - self.client.delete_index(self.config.index_name) - self._setup_pinecone_index() - - @staticmethod - def _generate_filter(where: dict): - query = {} - if where is None: - return query - - for k, v in where.items(): - query[k] = {"$eq": v} - return query - - def delete(self, where: dict): - """Delete from database. - :param ids: list of ids to delete - :type ids: list[str] - """ - # Deleting with filters is not supported for `starter` index type. - # Follow `https://docs.pinecone.io/docs/metadata-filtering#deleting-vectors-by-metadata-filter` for more details - db_filter = self._generate_filter(where) - try: - self.pinecone_index.delete(filter=db_filter) - except Exception as e: - print(f"Failed to delete from Pinecone: {e}") - return diff --git a/embedchain/embedchain/vectordb/qdrant.py b/embedchain/embedchain/vectordb/qdrant.py deleted file mode 100644 index cdac19cfa..000000000 --- a/embedchain/embedchain/vectordb/qdrant.py +++ /dev/null @@ -1,253 +0,0 @@ -import copy -import os -from typing import Any, Optional, Union - -try: - from qdrant_client import QdrantClient - from qdrant_client.http import models - from qdrant_client.http.models import Batch - from qdrant_client.models import Distance, VectorParams -except ImportError: - raise ImportError("Qdrant requires extra dependencies. Install with `pip install embedchain[qdrant]`") from None - -from tqdm import tqdm - -from embedchain.config.vector_db.qdrant import QdrantDBConfig -from embedchain.vectordb.base import BaseVectorDB - - -class QdrantDB(BaseVectorDB): - """ - Qdrant as vector database - """ - - def __init__(self, config: QdrantDBConfig = None): - """ - Qdrant as vector database - :param config. Qdrant database config to be used for connection - """ - if config is None: - config = QdrantDBConfig() - else: - if not isinstance(config, QdrantDBConfig): - raise TypeError( - "config is not a `QdrantDBConfig` instance. " - "Please make sure the type is right and that you are passing an instance." - ) - self.config = config - self.batch_size = self.config.batch_size - self.client = QdrantClient(url=os.getenv("QDRANT_URL"), api_key=os.getenv("QDRANT_API_KEY")) - # Call parent init here because embedder is needed - super().__init__(config=self.config) - - def _initialize(self): - """ - This method is needed because `embedder` attribute needs to be set externally before it can be initialized. - """ - if not self.embedder: - raise ValueError("Embedder not set. Please set an embedder with `set_embedder` before initialization.") - - self.collection_name = self._get_or_create_collection() - all_collections = self.client.get_collections() - collection_names = [collection.name for collection in all_collections.collections] - if self.collection_name not in collection_names: - self.client.recreate_collection( - collection_name=self.collection_name, - vectors_config=VectorParams( - size=self.embedder.vector_dimension, - distance=Distance.COSINE, - hnsw_config=self.config.hnsw_config, - quantization_config=self.config.quantization_config, - on_disk=self.config.on_disk, - ), - ) - - def _get_or_create_db(self): - return self.client - - def _get_or_create_collection(self): - return f"{self.config.collection_name}-{self.embedder.vector_dimension}".lower().replace("_", "-") - - def get(self, ids: Optional[list[str]] = None, where: Optional[dict[str, any]] = None, limit: Optional[int] = None): - """ - Get existing doc ids present in vector database - - :param ids: _list of doc ids to check for existence - :type ids: list[str] - :param where: to filter data - :type where: dict[str, any] - :param limit: The number of entries to be fetched - :type limit: Optional int, defaults to None - :return: All the existing IDs - :rtype: Set[str] - """ - - keys = set(where.keys() if where is not None else set()) - - qdrant_must_filters = [] - - if ids: - qdrant_must_filters.append( - models.FieldCondition( - key="identifier", - match=models.MatchAny( - any=ids, - ), - ) - ) - - if len(keys) > 0: - for key in keys: - qdrant_must_filters.append( - models.FieldCondition( - key="metadata.{}".format(key), - match=models.MatchValue( - value=where.get(key), - ), - ) - ) - - offset = 0 - existing_ids = [] - metadatas = [] - while offset is not None: - response = self.client.scroll( - collection_name=self.collection_name, - scroll_filter=models.Filter(must=qdrant_must_filters), - offset=offset, - limit=self.batch_size, - ) - offset = response[1] - for doc in response[0]: - existing_ids.append(doc.payload["identifier"]) - metadatas.append(doc.payload["metadata"]) - return {"ids": existing_ids, "metadatas": metadatas} - - def add( - self, - documents: list[str], - metadatas: list[object], - ids: list[str], - **kwargs: Optional[dict[str, any]], - ): - """add data in vector database - :param documents: list of texts to add - :type documents: list[str] - :param metadatas: list of metadata associated with docs - :type metadatas: list[object] - :param ids: ids of docs - :type ids: list[str] - """ - embeddings = self.embedder.embedding_fn(documents) - - payloads = [] - qdrant_ids = [] - for id, document, metadata in zip(ids, documents, metadatas): - metadata["text"] = document - qdrant_ids.append(id) - payloads.append({"identifier": id, "text": document, "metadata": copy.deepcopy(metadata)}) - - for i in tqdm(range(0, len(qdrant_ids), self.batch_size), desc="Adding data in batches"): - self.client.upsert( - collection_name=self.collection_name, - points=Batch( - ids=qdrant_ids[i : i + self.batch_size], - payloads=payloads[i : i + self.batch_size], - vectors=embeddings[i : i + self.batch_size], - ), - **kwargs, - ) - - def query( - self, - input_query: str, - n_results: int, - where: dict[str, any], - citations: bool = False, - **kwargs: Optional[dict[str, Any]], - ) -> Union[list[tuple[str, dict]], list[str]]: - """ - query contents from vector database based on vector similarity - :param input_query: query string - :type input_query: str - :param n_results: no of similar documents to fetch from database - :type n_results: int - :param where: Optional. to filter data - :type where: dict[str, any] - :param citations: we use citations boolean param to return context along with the answer. - :type citations: bool, default is False. - :return: The content of the document that matched your query, - along with url of the source and doc_id (if citations flag is true) - :rtype: list[str], if citations=False, otherwise list[tuple[str, str, str]] - """ - query_vector = self.embedder.embedding_fn([input_query])[0] - keys = set(where.keys() if where is not None else set()) - - qdrant_must_filters = [] - if len(keys) > 0: - for key in keys: - qdrant_must_filters.append( - models.FieldCondition( - key="metadata.{}".format(key), - match=models.MatchValue( - value=where.get(key), - ), - ) - ) - - results = self.client.search( - collection_name=self.collection_name, - query_filter=models.Filter(must=qdrant_must_filters), - query_vector=query_vector, - limit=n_results, - **kwargs, - ) - - contexts = [] - for result in results: - context = result.payload["text"] - if citations: - metadata = result.payload["metadata"] - metadata["score"] = result.score - contexts.append(tuple((context, metadata))) - else: - contexts.append(context) - return contexts - - def count(self) -> int: - response = self.client.get_collection(collection_name=self.collection_name) - return response.points_count - - def reset(self): - self.client.delete_collection(collection_name=self.collection_name) - self._initialize() - - def set_collection_name(self, name: str): - """ - Set the name of the collection. A collection is an isolated space for vectors. - - :param name: Name of the collection. - :type name: str - """ - if not isinstance(name, str): - raise TypeError("Collection name must be a string") - self.config.collection_name = name - self.collection_name = self._get_or_create_collection() - - @staticmethod - def _generate_query(where: dict): - must_fields = [] - for key, value in where.items(): - must_fields.append( - models.FieldCondition( - key=f"metadata.{key}", - match=models.MatchValue( - value=value, - ), - ) - ) - return models.Filter(must=must_fields) - - def delete(self, where: dict): - db_filter = self._generate_query(where) - self.client.delete(collection_name=self.collection_name, points_selector=db_filter) diff --git a/embedchain/embedchain/vectordb/weaviate.py b/embedchain/embedchain/vectordb/weaviate.py deleted file mode 100644 index 897412a64..000000000 --- a/embedchain/embedchain/vectordb/weaviate.py +++ /dev/null @@ -1,363 +0,0 @@ -import copy -import os -from typing import Optional, Union - -try: - import weaviate -except ImportError: - raise ImportError( - "Weaviate requires extra dependencies. Install with `pip install --upgrade 'embedchain[weaviate]'`" - ) from None - -from embedchain.config.vector_db.weaviate import WeaviateDBConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.vectordb.base import BaseVectorDB - - -@register_deserializable -class WeaviateDB(BaseVectorDB): - """ - Weaviate as vector database - """ - - def __init__( - self, - config: Optional[WeaviateDBConfig] = None, - ): - """Weaviate as vector database. - :param config: Weaviate database config, defaults to None - :type config: WeaviateDBConfig, optional - :raises ValueError: No config provided - """ - if config is None: - self.config = WeaviateDBConfig() - else: - if not isinstance(config, WeaviateDBConfig): - raise TypeError( - "config is not a `WeaviateDBConfig` instance. " - "Please make sure the type is right and that you are passing an instance." - ) - self.config = config - self.batch_size = self.config.batch_size - self.client = weaviate.Client( - url=os.environ.get("WEAVIATE_ENDPOINT"), - auth_client_secret=weaviate.AuthApiKey(api_key=os.environ.get("WEAVIATE_API_KEY")), - **self.config.extra_params, - ) - # Since weaviate uses graphQL, we need to keep track of metadata keys added in the vectordb. - # This is needed to filter data while querying. - self.metadata_keys = {"data_type", "doc_id", "url", "hash", "app_id"} - - # Call parent init here because embedder is needed - super().__init__(config=self.config) - - def _initialize(self): - """ - This method is needed because `embedder` attribute needs to be set externally before it can be initialized. - """ - - if not self.embedder: - raise ValueError("Embedder not set. Please set an embedder with `set_embedder` before initialization.") - - self.index_name = self._get_index_name() - if not self.client.schema.exists(self.index_name): - # id is a reserved field in Weaviate, hence we had to change the name of the id field to identifier - # The none vectorizer is crucial as we have our own custom embedding function - """ - TODO: wait for weaviate to add indexing on `object[]` data-type so that we can add filter while querying. - Once that is done, change `dataType` of "metadata" field to `object[]` and update the query below. - """ - class_obj = { - "classes": [ - { - "class": self.index_name, - "vectorizer": "none", - "properties": [ - { - "name": "identifier", - "dataType": ["text"], - }, - { - "name": "text", - "dataType": ["text"], - }, - { - "name": "metadata", - "dataType": [self.index_name + "_metadata"], - }, - ], - }, - { - "class": self.index_name + "_metadata", - "vectorizer": "none", - "properties": [ - { - "name": "data_type", - "dataType": ["text"], - }, - { - "name": "doc_id", - "dataType": ["text"], - }, - { - "name": "url", - "dataType": ["text"], - }, - { - "name": "hash", - "dataType": ["text"], - }, - { - "name": "app_id", - "dataType": ["text"], - }, - ], - }, - ] - } - - self.client.schema.create(class_obj) - - def get(self, ids: Optional[list[str]] = None, where: Optional[dict[str, any]] = None, limit: Optional[int] = None): - """ - Get existing doc ids present in vector database - :param ids: _list of doc ids to check for existance - :type ids: list[str] - :param where: to filter data - :type where: dict[str, any] - :return: ids - :rtype: Set[str] - """ - weaviate_where_operands = [] - - if ids: - for doc_id in ids: - weaviate_where_operands.append({"path": ["identifier"], "operator": "Equal", "valueText": doc_id}) - - keys = set(where.keys() if where is not None else set()) - if len(keys) > 0: - for key in keys: - weaviate_where_operands.append( - { - "path": ["metadata", self.index_name + "_metadata", key], - "operator": "Equal", - "valueText": where.get(key), - } - ) - - if len(weaviate_where_operands) == 1: - weaviate_where_clause = weaviate_where_operands[0] - else: - weaviate_where_clause = {"operator": "And", "operands": weaviate_where_operands} - - existing_ids = [] - metadatas = [] - cursor = None - offset = 0 - has_iterated_once = False - query_metadata_keys = self.metadata_keys.union(keys) - while cursor is not None or not has_iterated_once: - has_iterated_once = True - results = self._query_with_offset( - self.client.query.get( - self.index_name, - [ - "identifier", - weaviate.LinkTo("metadata", self.index_name + "_metadata", list(query_metadata_keys)), - ], - ) - .with_where(weaviate_where_clause) - .with_additional(["id"]) - .with_limit(limit or self.batch_size), - offset, - ) - - fetched_results = results["data"]["Get"].get(self.index_name, []) - if not fetched_results: - break - - for result in fetched_results: - existing_ids.append(result["identifier"]) - metadatas.append(result["metadata"][0]) - cursor = result["_additional"]["id"] - offset += 1 - - if limit is not None and len(existing_ids) >= limit: - break - - return {"ids": existing_ids, "metadatas": metadatas} - - def add(self, documents: list[str], metadatas: list[object], ids: list[str], **kwargs: Optional[dict[str, any]]): - """add data in vector database - :param documents: list of texts to add - :type documents: list[str] - :param metadatas: list of metadata associated with docs - :type metadatas: list[object] - :param ids: ids of docs - :type ids: list[str] - """ - embeddings = self.embedder.embedding_fn(documents) - self.client.batch.configure(batch_size=self.batch_size, timeout_retries=3) # Configure batch - with self.client.batch as batch: # Initialize a batch process - for id, text, metadata, embedding in zip(ids, documents, metadatas, embeddings): - doc = {"identifier": id, "text": text} - updated_metadata = {"text": text} - if metadata is not None: - updated_metadata.update(**metadata) - - obj_uuid = batch.add_data_object( - data_object=copy.deepcopy(doc), class_name=self.index_name, vector=embedding - ) - metadata_uuid = batch.add_data_object( - data_object=copy.deepcopy(updated_metadata), - class_name=self.index_name + "_metadata", - vector=embedding, - ) - batch.add_reference( - obj_uuid, self.index_name, "metadata", metadata_uuid, self.index_name + "_metadata", **kwargs - ) - - def query( - self, input_query: str, n_results: int, where: dict[str, any], citations: bool = False - ) -> Union[list[tuple[str, dict]], list[str]]: - """ - query contents from vector database based on vector similarity - :param input_query: query string - :type input_query: str - :param n_results: no of similar documents to fetch from database - :type n_results: int - :param where: Optional. to filter data - :type where: dict[str, any] - :param citations: we use citations boolean param to return context along with the answer. - :type citations: bool, default is False. - :return: The content of the document that matched your query, - along with url of the source and doc_id (if citations flag is true) - :rtype: list[str], if citations=False, otherwise list[tuple[str, str, str]] - """ - query_vector = self.embedder.embedding_fn([input_query])[0] - keys = set(where.keys() if where is not None else set()) - data_fields = ["text"] - query_metadata_keys = self.metadata_keys.union(keys) - if citations: - data_fields.append(weaviate.LinkTo("metadata", self.index_name + "_metadata", list(query_metadata_keys))) - - if len(keys) > 0: - weaviate_where_operands = [] - for key in keys: - weaviate_where_operands.append( - { - "path": ["metadata", self.index_name + "_metadata", key], - "operator": "Equal", - "valueText": where.get(key), - } - ) - if len(weaviate_where_operands) == 1: - weaviate_where_clause = weaviate_where_operands[0] - else: - weaviate_where_clause = {"operator": "And", "operands": weaviate_where_operands} - - results = ( - self.client.query.get(self.index_name, data_fields) - .with_where(weaviate_where_clause) - .with_near_vector({"vector": query_vector}) - .with_limit(n_results) - .with_additional(["distance"]) - .do() - ) - else: - results = ( - self.client.query.get(self.index_name, data_fields) - .with_near_vector({"vector": query_vector}) - .with_limit(n_results) - .with_additional(["distance"]) - .do() - ) - - if results["data"]["Get"].get(self.index_name) is None: - return [] - - docs = results["data"]["Get"].get(self.index_name) - contexts = [] - for doc in docs: - context = doc["text"] - if citations: - metadata = doc["metadata"][0] - score = doc["_additional"]["distance"] - metadata["score"] = score - contexts.append((context, metadata)) - else: - contexts.append(context) - return contexts - - def set_collection_name(self, name: str): - """ - Set the name of the collection. A collection is an isolated space for vectors. - :param name: Name of the collection. - :type name: str - """ - if not isinstance(name, str): - raise TypeError("Collection name must be a string") - self.config.collection_name = name - - def count(self) -> int: - """ - Count number of documents/chunks embedded in the database. - :return: number of documents - :rtype: int - """ - data = self.client.query.aggregate(self.index_name).with_meta_count().do() - return data["data"]["Aggregate"].get(self.index_name)[0]["meta"]["count"] - - def _get_or_create_db(self): - """Called during initialization""" - return self.client - - def reset(self): - """ - Resets the database. Deletes all embeddings irreversibly. - """ - # Delete all data from the database - self.client.batch.delete_objects( - self.index_name, where={"path": ["identifier"], "operator": "Like", "valueText": ".*"} - ) - - # Weaviate internally by default capitalizes the class name - def _get_index_name(self) -> str: - """Get the Weaviate index for a collection - :return: Weaviate index - :rtype: str - """ - return f"{self.config.collection_name}_{self.embedder.vector_dimension}".capitalize().replace("-", "_") - - @staticmethod - def _query_with_offset(query, offset): - if offset: - query.with_offset(offset) - results = query.do() - return results - - def _generate_query(self, where: dict): - weaviate_where_operands = [] - for key, value in where.items(): - weaviate_where_operands.append( - { - "path": ["metadata", self.index_name + "_metadata", key], - "operator": "Equal", - "valueText": value, - } - ) - - if len(weaviate_where_operands) == 1: - weaviate_where_clause = weaviate_where_operands[0] - else: - weaviate_where_clause = {"operator": "And", "operands": weaviate_where_operands} - - return weaviate_where_clause - - def delete(self, where: dict): - """Delete from database. - :param where: to filter data - :type where: dict[str, any] - """ - query = self._generate_query(where) - self.client.batch.delete_objects(self.index_name, where=query) diff --git a/embedchain/embedchain/vectordb/zilliz.py b/embedchain/embedchain/vectordb/zilliz.py deleted file mode 100644 index ca5544733..000000000 --- a/embedchain/embedchain/vectordb/zilliz.py +++ /dev/null @@ -1,252 +0,0 @@ -import logging -from typing import Any, Optional, Union - -from embedchain.config import ZillizDBConfig -from embedchain.helpers.json_serializable import register_deserializable -from embedchain.vectordb.base import BaseVectorDB - -try: - from pymilvus import ( - Collection, - CollectionSchema, - DataType, - FieldSchema, - MilvusClient, - connections, - utility, - ) -except ImportError: - raise ImportError( - "Zilliz requires extra dependencies. Install with `pip install --upgrade embedchain[milvus]`" - ) from None - -logger = logging.getLogger(__name__) - - -@register_deserializable -class ZillizVectorDB(BaseVectorDB): - """Base class for vector database.""" - - def __init__(self, config: ZillizDBConfig = None): - """Initialize the database. Save the config and client as an attribute. - - :param config: Database configuration class instance. - :type config: ZillizDBConfig - """ - - if config is None: - self.config = ZillizDBConfig() - else: - self.config = config - - self.client = MilvusClient( - uri=self.config.uri, - token=self.config.token, - ) - - self.connection = connections.connect( - uri=self.config.uri, - token=self.config.token, - ) - - super().__init__(config=self.config) - - def _initialize(self): - """ - This method is needed because `embedder` attribute needs to be set externally before it can be initialized. - - So it's can't be done in __init__ in one step. - """ - self._get_or_create_collection(self.config.collection_name) - - def _get_or_create_db(self): - """Get or create the database.""" - return self.client - - def _get_or_create_collection(self, name): - """ - Get or create a named collection. - - :param name: Name of the collection - :type name: str - """ - if utility.has_collection(name): - logger.info(f"[ZillizDB]: found an existing collection {name}, make sure the auto-id is disabled.") - self.collection = Collection(name) - else: - fields = [ - FieldSchema(name="id", dtype=DataType.VARCHAR, is_primary=True, max_length=512), - FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=2048), - FieldSchema(name="embeddings", dtype=DataType.FLOAT_VECTOR, dim=self.embedder.vector_dimension), - FieldSchema(name="metadata", dtype=DataType.JSON), - ] - - schema = CollectionSchema(fields, enable_dynamic_field=True) - self.collection = Collection(name=name, schema=schema) - - index = { - "index_type": "AUTOINDEX", - "metric_type": self.config.metric_type, - } - self.collection.create_index("embeddings", index) - return self.collection - - def get(self, ids: Optional[list[str]] = None, where: Optional[dict[str, any]] = None, limit: Optional[int] = None): - """ - Get existing doc ids present in vector database - - :param ids: list of doc ids to check for existence - :type ids: list[str] - :param where: Optional. to filter data - :type where: dict[str, Any] - :param limit: Optional. maximum number of documents - :type limit: Optional[int] - :return: Existing documents. - :rtype: Set[str] - """ - data_ids = [] - metadatas = [] - if self.collection.num_entities == 0 or self.collection.is_empty: - return {"ids": data_ids, "metadatas": metadatas} - - filter_ = "" - if ids: - filter_ = f'id in "{ids}"' - - if where: - if filter_: - filter_ += " and " - filter_ = f"{self._generate_zilliz_filter(where)}" - - results = self.client.query(collection_name=self.config.collection_name, filter=filter_, output_fields=["*"]) - for res in results: - data_ids.append(res.get("id")) - metadatas.append(res.get("metadata", {})) - - return {"ids": data_ids, "metadatas": metadatas} - - def add( - self, - documents: list[str], - metadatas: list[object], - ids: list[str], - **kwargs: Optional[dict[str, any]], - ): - """Add to database""" - embeddings = self.embedder.embedding_fn(documents) - - for id, doc, metadata, embedding in zip(ids, documents, metadatas, embeddings): - data = {"id": id, "text": doc, "embeddings": embedding, "metadata": metadata} - self.client.insert(collection_name=self.config.collection_name, data=data, **kwargs) - - self.collection.load() - self.collection.flush() - self.client.flush(self.config.collection_name) - - def query( - self, - input_query: str, - n_results: int, - where: dict[str, Any], - citations: bool = False, - **kwargs: Optional[dict[str, Any]], - ) -> Union[list[tuple[str, dict]], list[str]]: - """ - Query contents from vector database based on vector similarity - - :param input_query: query string - :type input_query: str - :param n_results: no of similar documents to fetch from database - :type n_results: int - :param where: to filter data - :type where: dict[str, Any] - :raises InvalidDimensionException: Dimensions do not match. - :param citations: we use citations boolean param to return context along with the answer. - :type citations: bool, default is False. - :return: The content of the document that matched your query, - along with url of the source and doc_id (if citations flag is true) - :rtype: list[str], if citations=False, otherwise list[tuple[str, str, str]] - """ - - if self.collection.is_empty: - return [] - - output_fields = ["*"] - input_query_vector = self.embedder.embedding_fn([input_query]) - query_vector = input_query_vector[0] - - query_filter = self._generate_zilliz_filter(where) - query_result = self.client.search( - collection_name=self.config.collection_name, - data=[query_vector], - filter=query_filter, - limit=n_results, - output_fields=output_fields, - **kwargs, - ) - query_result = query_result[0] - contexts = [] - for query in query_result: - data = query["entity"] - score = query["distance"] - context = data["text"] - - if citations: - metadata = data.get("metadata", {}) - metadata["score"] = score - contexts.append(tuple((context, metadata))) - else: - contexts.append(context) - return contexts - - def count(self) -> int: - """ - Count number of documents/chunks embedded in the database. - - :return: number of documents - :rtype: int - """ - return self.collection.num_entities - - def reset(self, collection_names: list[str] = None): - """ - Resets the database. Deletes all embeddings irreversibly. - """ - if self.config.collection_name: - if collection_names: - for collection_name in collection_names: - if collection_name in self.client.list_collections(): - self.client.drop_collection(collection_name=collection_name) - else: - self.client.drop_collection(collection_name=self.config.collection_name) - self._get_or_create_collection(self.config.collection_name) - - def set_collection_name(self, name: str): - """ - Set the name of the collection. A collection is an isolated space for vectors. - - :param name: Name of the collection. - :type name: str - """ - if not isinstance(name, str): - raise TypeError("Collection name must be a string") - self.config.collection_name = name - - def _generate_zilliz_filter(self, where: dict[str, str]): - operands = [] - for key, value in where.items(): - operands.append(f'(metadata["{key}"] == "{value}")') - return " and ".join(operands) - - def delete(self, where: dict[str, Any]): - """ - Delete the embeddings from DB. Zilliz only support deleting with keys. - - - :param keys: Primary keys of the table entries to delete. - :type keys: Union[list, str, int] - """ - data = self.get(where=where) - keys = data.get("ids", []) - if keys: - self.client.delete(collection_name=self.config.collection_name, pks=keys) diff --git a/embedchain/examples/api_server/.dockerignore b/embedchain/examples/api_server/.dockerignore deleted file mode 100644 index 1dce42e87..000000000 --- a/embedchain/examples/api_server/.dockerignore +++ /dev/null @@ -1,8 +0,0 @@ -__pycache__/ -database -db -pyenv -venv -.env -.git -trash_files/ diff --git a/embedchain/examples/api_server/.gitignore b/embedchain/examples/api_server/.gitignore deleted file mode 100644 index 2227fe3e2..000000000 --- a/embedchain/examples/api_server/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -__pycache__ -db -database -pyenv -venv -.env -trash_files/ -.ideas.md \ No newline at end of file diff --git a/embedchain/examples/api_server/Dockerfile b/embedchain/examples/api_server/Dockerfile deleted file mode 100644 index 6d5a7be87..000000000 --- a/embedchain/examples/api_server/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM python:3.11 AS backend - -WORKDIR /usr/src/api -COPY requirements.txt . -RUN pip install -r requirements.txt - -COPY . . - -EXPOSE 5000 - -ENV FLASK_APP=api_server.py - -ENV FLASK_RUN_EXTRA_FILES=/usr/src/api/* -ENV FLASK_ENV=development - -CMD ["flask", "run", "--host=0.0.0.0", "--reload"] diff --git a/embedchain/examples/api_server/README.md b/embedchain/examples/api_server/README.md deleted file mode 100644 index 1d9fa612b..000000000 --- a/embedchain/examples/api_server/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# API Server - -This is a docker template to create your own API Server using the embedchain package. To know more about the API Server and how to use it, go [here](https://docs.embedchain.ai/examples/api_server). \ No newline at end of file diff --git a/embedchain/examples/api_server/api_server.py b/embedchain/examples/api_server/api_server.py deleted file mode 100644 index f8d4d4d1a..000000000 --- a/embedchain/examples/api_server/api_server.py +++ /dev/null @@ -1,57 +0,0 @@ -import logging - -from flask import Flask, jsonify, request - -from embedchain import App - -app = Flask(__name__) - - -logger = logging.getLogger(__name__) - - -@app.route("/add", methods=["POST"]) -def add(): - data = request.get_json() - data_type = data.get("data_type") - url_or_text = data.get("url_or_text") - if data_type and url_or_text: - try: - App().add(url_or_text, data_type=data_type) - return jsonify({"data": f"Added {data_type}: {url_or_text}"}), 200 - except Exception: - logger.exception(f"Failed to add {data_type=}: {url_or_text=}") - return jsonify({"error": f"Failed to add {data_type}: {url_or_text}"}), 500 - return jsonify({"error": "Invalid request. Please provide 'data_type' and 'url_or_text' in JSON format."}), 400 - - -@app.route("/query", methods=["POST"]) -def query(): - data = request.get_json() - question = data.get("question") - if question: - try: - response = App().query(question) - return jsonify({"data": response}), 200 - except Exception: - logger.exception(f"Failed to query {question=}") - return jsonify({"error": "An error occurred. Please try again!"}), 500 - return jsonify({"error": "Invalid request. Please provide 'question' in JSON format."}), 400 - - -@app.route("/chat", methods=["POST"]) -def chat(): - data = request.get_json() - question = data.get("question") - if question: - try: - response = App().chat(question) - return jsonify({"data": response}), 200 - except Exception: - logger.exception(f"Failed to chat {question=}") - return jsonify({"error": "An error occurred. Please try again!"}), 500 - return jsonify({"error": "Invalid request. Please provide 'question' in JSON format."}), 400 - - -if __name__ == "__main__": - app.run(host="0.0.0.0", port=5000, debug=False) diff --git a/embedchain/examples/api_server/docker-compose.yml b/embedchain/examples/api_server/docker-compose.yml deleted file mode 100644 index 8fa3fc817..000000000 --- a/embedchain/examples/api_server/docker-compose.yml +++ /dev/null @@ -1,15 +0,0 @@ -version: "3.9" - -services: - backend: - container_name: embedchain_api - restart: unless-stopped - build: - context: . - dockerfile: Dockerfile - env_file: - - variables.env - ports: - - "5000:5000" - volumes: - - .:/usr/src/api diff --git a/embedchain/examples/api_server/requirements.txt b/embedchain/examples/api_server/requirements.txt deleted file mode 100644 index 39e066ada..000000000 --- a/embedchain/examples/api_server/requirements.txt +++ /dev/null @@ -1,12 +0,0 @@ -flask==2.3.2 -youtube-transcript-api==0.6.1 -pytube==15.0.0 -beautifulsoup4==4.12.3 -slack-sdk==3.21.3 -huggingface_hub==0.23.0 -gitpython==3.1.38 -yt_dlp==2023.11.14 -PyGithub==1.59.1 -feedparser==6.0.10 -newspaper3k==0.2.8 -listparser==0.19 \ No newline at end of file diff --git a/embedchain/examples/api_server/variables.env b/embedchain/examples/api_server/variables.env deleted file mode 100644 index da6725993..000000000 --- a/embedchain/examples/api_server/variables.env +++ /dev/null @@ -1 +0,0 @@ -OPENAI_API_KEY="" \ No newline at end of file diff --git a/embedchain/examples/chainlit/.gitignore b/embedchain/examples/chainlit/.gitignore deleted file mode 100644 index 2121b2589..000000000 --- a/embedchain/examples/chainlit/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.chainlit diff --git a/embedchain/examples/chainlit/README.md b/embedchain/examples/chainlit/README.md deleted file mode 100644 index d54e69656..000000000 --- a/embedchain/examples/chainlit/README.md +++ /dev/null @@ -1,17 +0,0 @@ -## Chainlit + Embedchain Demo - -In this example, we will learn how to use Chainlit and Embedchain together - -## Setup - -First, install the required packages: - -```bash -pip install -r requirements.txt -``` - -## Run the app locally, - -``` -chainlit run app.py -``` diff --git a/embedchain/examples/chainlit/app.py b/embedchain/examples/chainlit/app.py deleted file mode 100644 index f2de4b0bd..000000000 --- a/embedchain/examples/chainlit/app.py +++ /dev/null @@ -1,35 +0,0 @@ -import os - -import chainlit as cl - -from embedchain import App - -os.environ["OPENAI_API_KEY"] = "sk-xxx" - - -@cl.on_chat_start -async def on_chat_start(): - app = App.from_config( - config={ - "app": {"config": {"name": "chainlit-app"}}, - "llm": { - "config": { - "stream": True, - } - }, - } - ) - # import your data here - app.add("https://www.forbes.com/profile/elon-musk/") - app.collect_metrics = False - cl.user_session.set("app", app) - - -@cl.on_message -async def on_message(message: cl.Message): - app = cl.user_session.get("app") - msg = cl.Message(content="") - for chunk in await cl.make_async(app.chat)(message.content): - await msg.stream_token(chunk) - - await msg.send() diff --git a/embedchain/examples/chainlit/chainlit.md b/embedchain/examples/chainlit/chainlit.md deleted file mode 100644 index d3de410e4..000000000 --- a/embedchain/examples/chainlit/chainlit.md +++ /dev/null @@ -1,15 +0,0 @@ -# Welcome to Embedchain! 🚀 - -Hello! 👋 Excited to see you join us. With Embedchain and Chainlit, create ChatGPT like apps effortlessly. - -## Quick Start 🌟 - -- **Embedchain Docs:** Get started with our comprehensive [Embedchain Documentation](https://docs.embedchain.ai/) 📚 -- **Discord Community:** Join our discord [Embedchain Discord](https://discord.gg/CUU9FPhRNt) to ask questions, share your projects, and connect with other developers! 💬 -- **UI Guide**: Master Chainlit with [Chainlit Documentation](https://docs.chainlit.io/) ⛓️ - -Happy building with Embedchain! 🎉 - -## Customize welcome screen - -Edit chainlit.md in your project root to change this welcome message. diff --git a/embedchain/examples/chainlit/requirements.txt b/embedchain/examples/chainlit/requirements.txt deleted file mode 100644 index 1604c5f9d..000000000 --- a/embedchain/examples/chainlit/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -chainlit==0.7.700 -embedchain==0.1.57 diff --git a/embedchain/examples/chat-pdf/README.md b/embedchain/examples/chat-pdf/README.md deleted file mode 100644 index 2a09c8bfc..000000000 --- a/embedchain/examples/chat-pdf/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Embedchain Chat with PDF App - -You can easily create and deploy your own `Chat-with-PDF` App using Embedchain. - -Checkout the live demo we created for [chat with PDF](https://embedchain.ai/demo/chat-pdf). - -Here are few simple steps for you to create and deploy your app: - -1. Fork the embedchain repo from [Github](https://github.com/embedchain/embedchain). - -If you run into problems with forking, please refer to [github docs](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) for forking a repo. - -2. Navigate to `chat-pdf` example app from your forked repo: - -```bash -cd /examples/chat-pdf -``` - -3. Run your app in development environment with simple commands - -```bash -pip install -r requirements.txt -ec dev -``` - -Feel free to improve our simple `chat-pdf` streamlit app and create pull request to showcase your app [here](https://docs.embedchain.ai/examples/showcase) - -4. You can easily deploy your app using Streamlit interface - -Connect your Github account with Streamlit and refer this [guide](https://docs.streamlit.io/streamlit-community-cloud/deploy-your-app) to deploy your app. - -You can also use the deploy button from your streamlit website you see when running `ec dev` command. diff --git a/embedchain/examples/chat-pdf/app.py b/embedchain/examples/chat-pdf/app.py deleted file mode 100644 index 73800605d..000000000 --- a/embedchain/examples/chat-pdf/app.py +++ /dev/null @@ -1,160 +0,0 @@ -import os -import queue -import re -import tempfile -import threading - -import streamlit as st - -from embedchain import App -from embedchain.config import BaseLlmConfig -from embedchain.helpers.callbacks import StreamingStdOutCallbackHandlerYield, generate - - -def embedchain_bot(db_path, api_key): - return App.from_config( - config={ - "llm": { - "provider": "openai", - "config": { - "model": "gpt-4o-mini", - "temperature": 0.5, - "max_tokens": 1000, - "top_p": 1, - "stream": True, - "api_key": api_key, - }, - }, - "vectordb": { - "provider": "chroma", - "config": {"collection_name": "chat-pdf", "dir": db_path, "allow_reset": True}, - }, - "embedder": {"provider": "openai", "config": {"api_key": api_key}}, - "chunker": {"chunk_size": 2000, "chunk_overlap": 0, "length_function": "len"}, - } - ) - - -def get_db_path(): - tmpdirname = tempfile.mkdtemp() - return tmpdirname - - -def get_ec_app(api_key): - if "app" in st.session_state: - print("Found app in session state") - app = st.session_state.app - else: - print("Creating app") - db_path = get_db_path() - app = embedchain_bot(db_path, api_key) - st.session_state.app = app - return app - - -with st.sidebar: - openai_access_token = st.text_input("OpenAI API Key", key="api_key", type="password") - "WE DO NOT STORE YOUR OPENAI KEY." - "Just paste your OpenAI API key here and we'll use it to power the chatbot. [Get your OpenAI API key](https://platform.openai.com/api-keys)" # noqa: E501 - - if st.session_state.api_key: - app = get_ec_app(st.session_state.api_key) - - pdf_files = st.file_uploader("Upload your PDF files", accept_multiple_files=True, type="pdf") - add_pdf_files = st.session_state.get("add_pdf_files", []) - for pdf_file in pdf_files: - file_name = pdf_file.name - if file_name in add_pdf_files: - continue - try: - if not st.session_state.api_key: - st.error("Please enter your OpenAI API Key") - st.stop() - temp_file_name = None - with tempfile.NamedTemporaryFile(mode="wb", delete=False, prefix=file_name, suffix=".pdf") as f: - f.write(pdf_file.getvalue()) - temp_file_name = f.name - if temp_file_name: - st.markdown(f"Adding {file_name} to knowledge base...") - app.add(temp_file_name, data_type="pdf_file") - st.markdown("") - add_pdf_files.append(file_name) - os.remove(temp_file_name) - st.session_state.messages.append({"role": "assistant", "content": f"Added {file_name} to knowledge base!"}) - except Exception as e: - st.error(f"Error adding {file_name} to knowledge base: {e}") - st.stop() - st.session_state["add_pdf_files"] = add_pdf_files - -st.title("📄 Embedchain - Chat with PDF") -styled_caption = '

🚀 An Embedchain app powered by OpenAI!

' # noqa: E501 -st.markdown(styled_caption, unsafe_allow_html=True) - -if "messages" not in st.session_state: - st.session_state.messages = [ - { - "role": "assistant", - "content": """ - Hi! I'm chatbot powered by Embedchain, which can answer questions about your pdf documents.\n - Upload your pdf documents here and I'll answer your questions about them! - """, - } - ] - -for message in st.session_state.messages: - with st.chat_message(message["role"]): - st.markdown(message["content"]) - -if prompt := st.chat_input("Ask me anything!"): - if not st.session_state.api_key: - st.error("Please enter your OpenAI API Key", icon="🤖") - st.stop() - - app = get_ec_app(st.session_state.api_key) - - with st.chat_message("user"): - st.session_state.messages.append({"role": "user", "content": prompt}) - st.markdown(prompt) - - with st.chat_message("assistant"): - msg_placeholder = st.empty() - msg_placeholder.markdown("Thinking...") - full_response = "" - - q = queue.Queue() - - def app_response(result): - llm_config = app.llm.config.as_dict() - llm_config["callbacks"] = [StreamingStdOutCallbackHandlerYield(q=q)] - config = BaseLlmConfig(**llm_config) - answer, citations = app.chat(prompt, config=config, citations=True) - result["answer"] = answer - result["citations"] = citations - - results = {} - thread = threading.Thread(target=app_response, args=(results,)) - thread.start() - - for answer_chunk in generate(q): - full_response += answer_chunk - msg_placeholder.markdown(full_response) - - thread.join() - answer, citations = results["answer"], results["citations"] - if citations: - full_response += "\n\n**Sources**:\n" - sources = [] - for i, citation in enumerate(citations): - source = citation[1]["url"] - pattern = re.compile(r"([^/]+)\.[^\.]+\.pdf$") - match = pattern.search(source) - if match: - source = match.group(1) + ".pdf" - sources.append(source) - sources = list(set(sources)) - for source in sources: - full_response += f"- {source}\n" - - msg_placeholder.markdown(full_response) - print("Answer: ", full_response) - st.session_state.messages.append({"role": "assistant", "content": full_response}) diff --git a/embedchain/examples/chat-pdf/embedchain.json b/embedchain/examples/chat-pdf/embedchain.json deleted file mode 100644 index 32dec2933..000000000 --- a/embedchain/examples/chat-pdf/embedchain.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "provider": "streamlit.io" -} \ No newline at end of file diff --git a/embedchain/examples/chat-pdf/requirements.txt b/embedchain/examples/chat-pdf/requirements.txt deleted file mode 100644 index b9bbe5aad..000000000 --- a/embedchain/examples/chat-pdf/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -streamlit -embedchain -langchain-text-splitters -pysqlite3-binary diff --git a/embedchain/examples/discord_bot/.dockerignore b/embedchain/examples/discord_bot/.dockerignore deleted file mode 100644 index 1dce42e87..000000000 --- a/embedchain/examples/discord_bot/.dockerignore +++ /dev/null @@ -1,8 +0,0 @@ -__pycache__/ -database -db -pyenv -venv -.env -.git -trash_files/ diff --git a/embedchain/examples/discord_bot/.gitignore b/embedchain/examples/discord_bot/.gitignore deleted file mode 100644 index ba288ed39..000000000 --- a/embedchain/examples/discord_bot/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -__pycache__ -db -database -pyenv -venv -.env -trash_files/ diff --git a/embedchain/examples/discord_bot/Dockerfile b/embedchain/examples/discord_bot/Dockerfile deleted file mode 100644 index c4f45e58f..000000000 --- a/embedchain/examples/discord_bot/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM python:3.11-slim - -WORKDIR /usr/src/discord_bot -COPY requirements.txt . -RUN pip install -r requirements.txt - -COPY . . - -CMD ["python", "discord_bot.py"] diff --git a/embedchain/examples/discord_bot/README.md b/embedchain/examples/discord_bot/README.md deleted file mode 100644 index 2d581871c..000000000 --- a/embedchain/examples/discord_bot/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Discord Bot - -This is a docker template to create your own Discord bot using the embedchain package. To know more about the bot and how to use it, go [here](https://docs.embedchain.ai/examples/discord_bot). - -To run this use the following command, - -```bash -docker run --name discord-bot -e OPENAI_API_KEY=sk-xxx -e DISCORD_BOT_TOKEN=xxx -p 8080:8080 embedchain/discord-bot:latest -``` diff --git a/embedchain/examples/discord_bot/discord_bot.py b/embedchain/examples/discord_bot/discord_bot.py deleted file mode 100644 index c7bad2689..000000000 --- a/embedchain/examples/discord_bot/discord_bot.py +++ /dev/null @@ -1,76 +0,0 @@ -import os - -import discord -from discord.ext import commands -from dotenv import load_dotenv - -from embedchain import App - -load_dotenv() -intents = discord.Intents.default() -intents.message_content = True - -bot = commands.Bot(command_prefix="/ec ", intents=intents) -root_folder = os.getcwd() - - -def initialize_chat_bot(): - global chat_bot - chat_bot = App() - - -@bot.event -async def on_ready(): - print(f"Logged in as {bot.user.name}") - initialize_chat_bot() - - -@bot.event -async def on_command_error(ctx, error): - if isinstance(error, commands.CommandNotFound): - await send_response(ctx, "Invalid command. Please refer to the documentation for correct syntax.") - else: - print("Error occurred during command execution:", error) - - -@bot.command() -async def add(ctx, data_type: str, *, url_or_text: str): - print(f"User: {ctx.author.name}, Data Type: {data_type}, URL/Text: {url_or_text}") - try: - chat_bot.add(data_type, url_or_text) - await send_response(ctx, f"Added {data_type} : {url_or_text}") - except Exception as e: - await send_response(ctx, f"Failed to add {data_type} : {url_or_text}") - print("Error occurred during 'add' command:", e) - - -@bot.command() -async def query(ctx, *, question: str): - print(f"User: {ctx.author.name}, Query: {question}") - try: - response = chat_bot.query(question) - await send_response(ctx, response) - except Exception as e: - await send_response(ctx, "An error occurred. Please try again!") - print("Error occurred during 'query' command:", e) - - -@bot.command() -async def chat(ctx, *, question: str): - print(f"User: {ctx.author.name}, Query: {question}") - try: - response = chat_bot.chat(question) - await send_response(ctx, response) - except Exception as e: - await send_response(ctx, "An error occurred. Please try again!") - print("Error occurred during 'chat' command:", e) - - -async def send_response(ctx, message): - if ctx.guild is None: - await ctx.send(message) - else: - await ctx.reply(message) - - -bot.run(os.environ["DISCORD_BOT_TOKEN"]) diff --git a/embedchain/examples/discord_bot/docker-compose.yml b/embedchain/examples/discord_bot/docker-compose.yml deleted file mode 100644 index 69baff0d8..000000000 --- a/embedchain/examples/discord_bot/docker-compose.yml +++ /dev/null @@ -1,11 +0,0 @@ -version: "3.9" - -services: - backend: - container_name: embedchain_discord_bot - restart: unless-stopped - build: - context: . - dockerfile: Dockerfile - env_file: - - variables.env \ No newline at end of file diff --git a/embedchain/examples/discord_bot/requirements.txt b/embedchain/examples/discord_bot/requirements.txt deleted file mode 100644 index 9cdaf53e3..000000000 --- a/embedchain/examples/discord_bot/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -discord==2.3.1 -embedchain==0.1.57 -python-dotenv==1.0.0 \ No newline at end of file diff --git a/embedchain/examples/discord_bot/variables.env b/embedchain/examples/discord_bot/variables.env deleted file mode 100644 index 7f3bd8975..000000000 --- a/embedchain/examples/discord_bot/variables.env +++ /dev/null @@ -1,2 +0,0 @@ -OPENAI_API_KEY="" -DISCORD_BOT_TOKEN="" \ No newline at end of file diff --git a/embedchain/examples/mistral-streamlit/README.md b/embedchain/examples/mistral-streamlit/README.md deleted file mode 100644 index 1bd80f83f..000000000 --- a/embedchain/examples/mistral-streamlit/README.md +++ /dev/null @@ -1,7 +0,0 @@ -### Streamlit Chat bot App (Embedchain + Mistral) - -To run it locally, - -```bash -streamlit run app.py -``` diff --git a/embedchain/examples/mistral-streamlit/app.py b/embedchain/examples/mistral-streamlit/app.py deleted file mode 100644 index 9df85fa32..000000000 --- a/embedchain/examples/mistral-streamlit/app.py +++ /dev/null @@ -1,72 +0,0 @@ -import os - -import streamlit as st - -from embedchain import App - - -@st.cache_resource -def ec_app(): - return App.from_config(config_path="config.yaml") - - -with st.sidebar: - huggingface_access_token = st.text_input("Hugging face Token", key="chatbot_api_key", type="password") - "[Get Hugging Face Access Token](https://huggingface.co/settings/tokens)" - "[View the source code](https://github.com/embedchain/examples/mistral-streamlit)" - - -st.title("💬 Chatbot") -st.caption("🚀 An Embedchain app powered by Mistral!") -if "messages" not in st.session_state: - st.session_state.messages = [ - { - "role": "assistant", - "content": """ - Hi! I'm a chatbot. I can answer questions and learn new things!\n - Ask me anything and if you want me to learn something do `/add `.\n - I can learn mostly everything. :) - """, - } - ] - -for message in st.session_state.messages: - with st.chat_message(message["role"]): - st.markdown(message["content"]) - -if prompt := st.chat_input("Ask me anything!"): - if not st.session_state.chatbot_api_key: - st.error("Please enter your Hugging Face Access Token") - st.stop() - - os.environ["HUGGINGFACE_ACCESS_TOKEN"] = st.session_state.chatbot_api_key - app = ec_app() - - if prompt.startswith("/add"): - with st.chat_message("user"): - st.markdown(prompt) - st.session_state.messages.append({"role": "user", "content": prompt}) - prompt = prompt.replace("/add", "").strip() - with st.chat_message("assistant"): - message_placeholder = st.empty() - message_placeholder.markdown("Adding to knowledge base...") - app.add(prompt) - message_placeholder.markdown(f"Added {prompt} to knowledge base!") - st.session_state.messages.append({"role": "assistant", "content": f"Added {prompt} to knowledge base!"}) - st.stop() - - with st.chat_message("user"): - st.markdown(prompt) - st.session_state.messages.append({"role": "user", "content": prompt}) - - with st.chat_message("assistant"): - msg_placeholder = st.empty() - msg_placeholder.markdown("Thinking...") - full_response = "" - - for response in app.chat(prompt): - msg_placeholder.empty() - full_response += response - - msg_placeholder.markdown(full_response) - st.session_state.messages.append({"role": "assistant", "content": full_response}) diff --git a/embedchain/examples/mistral-streamlit/config.yaml b/embedchain/examples/mistral-streamlit/config.yaml deleted file mode 100644 index 6b5971348..000000000 --- a/embedchain/examples/mistral-streamlit/config.yaml +++ /dev/null @@ -1,17 +0,0 @@ -app: - config: - name: 'mistral-streamlit-app' - -llm: - provider: huggingface - config: - model: 'mistralai/Mixtral-8x7B-Instruct-v0.1' - temperature: 0.1 - max_tokens: 250 - top_p: 0.1 - stream: true - -embedder: - provider: huggingface - config: - model: 'sentence-transformers/all-mpnet-base-v2' diff --git a/embedchain/examples/mistral-streamlit/requirements.txt b/embedchain/examples/mistral-streamlit/requirements.txt deleted file mode 100644 index b864076ae..000000000 --- a/embedchain/examples/mistral-streamlit/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -streamlit==1.29.0 -embedchain diff --git a/embedchain/examples/nextjs/README.md b/embedchain/examples/nextjs/README.md deleted file mode 100644 index e2c87b3f6..000000000 --- a/embedchain/examples/nextjs/README.md +++ /dev/null @@ -1,129 +0,0 @@ -Fork this repo on [Github](https://github.com/embedchain/embedchain) to create your own NextJS discord and slack bot powered by Embedchain app. - -If you run into problems with forking, please refer to [github docs](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) for forking a repo. - -We will work from the examples/nextjs folder so change your current working directory by running the command - `cd /examples/nextjs` - -# Installation - -First, lets start by install all the required packages and dependencies. - -- Install all the required python packages by running `pip install -r requirements.txt`. - -- We will use [Fly.io](https://fly.io/) to deploy our embedchain app and discord/slack bot. Follow the step one to install [Fly.io CLI](https://docs.embedchain.ai/deployment/fly_io#step-1-install-flyctl-command-line) - -# Developement - -## Embedchain App - -First, lets get started by creating an Embedchain app powered with the knowledge of NextJS. We have already created an embedchain app using FastAPI in `ec_app` folder for you. Feel free to ingest data of your choice to power the App. - ---- -**NOTE** - -Create `.env` file in this folder and set your OpenAI API key as shown in `.env.example` file. If you want to use other open-source models, feel free to change the app config in `app.py`. More details for using custom configuration for Embedchain app is [available here](https://docs.embedchain.ai/api-reference/advanced/configuration). - ---- - -Before running the ec commands to develope/deploy the app, open `fly.toml` file and update the `name` variable to something unique. This is important as `fly.io` requires users to provide a globally unique deployment app names. - -Now, we need to launch this application with fly.io. You can see your app on [fly.io dashboard](https://fly.io/dashboard). Run the following command to launch your app on fly.io: -```bash -fly launch --no-deploy -``` - -To run the app in development: - -```bash -ec dev #To run the app in development environment -``` - -Run `ec deploy` to deploy your app on Fly.io. Once you deploy your app, save the endpoint on which our discord and slack bot will send requests. - - -## Discord bot - -For discord bot, you will need to create the bot on discord developer portal and get the discord bot token and your discord bot name. - -While keeping in mind the following note, create the discord bot by following the instructions from our [discord bot docs](https://docs.embedchain.ai/examples/discord_bot) and get discord bot token. - ---- -**NOTE** - -You do not need to set `OPENAI_API_KEY` to run this discord bot. Follow the remaining instructions to create a discord bot app. We recommend you to give the following sets of bot permissions to run the discord bot without errors: - -``` -(General Permissions) -Read Message/View Channels - -(Text Permissions) -Send Messages -Create Public Thread -Create Private Thread -Send Messages in Thread -Manage Threads -Embed Links -Read Message History -``` ---- - -Once you have your discord bot token and discord app name. Navigate to `nextjs_discord` folder and create `.env` file and define your discord bot token, discord bot name and endpoint of your embedchain app as shown in `.env.example` file. - -To run the app in development: - -```bash -python app.py #To run the app in development environment -``` - -Before deploying the app, open `fly.toml` file and update the `name` variable to something unique. This is important as `fly.io` requires users to provide a globally unique deployment app names. - -Now, we need to launch this application with fly.io. You can see your app on [fly.io dashboard](https://fly.io/dashboard). Run the following command to launch your app on fly.io: -```bash -fly launch --no-deploy -``` - -Run `ec deploy` to deploy your app on Fly.io. Once you deploy your app, your discord bot will be live! - - -## Slack bot - -For Slack bot, you will need to create the bot on slack developer portal and get the slack bot token and slack app token. - -### Setup - -- Create a workspace on Slack if you don't have one already by clicking [here](https://slack.com/intl/en-in/). -- Create a new App on your Slack account by going [here](https://api.slack.com/apps). -- Select `From Scratch`, then enter the Bot Name and select your workspace. -- Go to `App Credentials` section on the `Basic Information` tab from the left sidebar, create your app token and save it in your `.env` file as `SLACK_APP_TOKEN`. -- Go to `Socket Mode` tab from the left sidebar and enable the socket mode to listen to slack message from your workspace. -- (Optional) Under the `App Home` tab you can change your App display name and default name. -- Navigate to `Event Subscription` tab, and enable the event subscription so that we can listen to slack events. -- Once you enable the event subscription, you will need to subscribe to bot events to authorize the bot to listen to app mention events of the bot. Do that by tapping on `Add Bot User Event` button and select `app_mention`. -- On the left Sidebar, go to `OAuth and Permissions` and add the following scopes under `Bot Token Scopes`: -```text -app_mentions:read -channels:history -channels:read -chat:write -emoji:read -reactions:write -reactions:read -``` -- Now select the option `Install to Workspace` and after it's done, copy the `Bot User OAuth Token` and set it in your `.env` file as `SLACK_BOT_TOKEN`. - -Once you have your slack bot token and slack app token. Navigate to `nextjs_slack` folder and create `.env` file and define your slack bot token, slack app token and endpoint of your embedchain app as shown in `.env.example` file. - -To run the app in development: - -```bash -python app.py #To run the app in development environment -``` - -Before deploying the app, open `fly.toml` file and update the `name` variable to something unique. This is important as `fly.io` requires users to provide a globally unique deployment app names. - -Now, we need to launch this application with fly.io. You can see your app on [fly.io dashboard](https://fly.io/dashboard). Run the following command to launch your app on fly.io: -```bash -fly launch --no-deploy -``` - -Run `ec deploy` to deploy your app on Fly.io. Once you deploy your app, your slack bot will be live! diff --git a/embedchain/examples/nextjs/ec_app/.dockerignore b/embedchain/examples/nextjs/ec_app/.dockerignore deleted file mode 100644 index 9f4c740db..000000000 --- a/embedchain/examples/nextjs/ec_app/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -db/ \ No newline at end of file diff --git a/embedchain/examples/nextjs/ec_app/.env.example b/embedchain/examples/nextjs/ec_app/.env.example deleted file mode 100644 index b29363f94..000000000 --- a/embedchain/examples/nextjs/ec_app/.env.example +++ /dev/null @@ -1 +0,0 @@ -OPENAI_API_KEY=sk-xxx \ No newline at end of file diff --git a/embedchain/examples/nextjs/ec_app/Dockerfile b/embedchain/examples/nextjs/ec_app/Dockerfile deleted file mode 100644 index 9eac80cee..000000000 --- a/embedchain/examples/nextjs/ec_app/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM python:3.11-slim - -WORKDIR /app - -COPY requirements.txt /app/ - -RUN pip install -r requirements.txt - -COPY . /app - -EXPOSE 8080 - -CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"] diff --git a/embedchain/examples/nextjs/ec_app/app.py b/embedchain/examples/nextjs/ec_app/app.py deleted file mode 100644 index 003543c46..000000000 --- a/embedchain/examples/nextjs/ec_app/app.py +++ /dev/null @@ -1,56 +0,0 @@ -from dotenv import load_dotenv -from fastapi import FastAPI, responses -from pydantic import BaseModel - -from embedchain import App - -load_dotenv(".env") - -app = FastAPI(title="Embedchain FastAPI App") -embedchain_app = App() - - -class SourceModel(BaseModel): - source: str - - -class QuestionModel(BaseModel): - question: str - - -@app.post("/add") -async def add_source(source_model: SourceModel): - """ - Adds a new source to the EmbedChain app. - Expects a JSON with a "source" key. - """ - source = source_model.source - embedchain_app.add(source) - return {"message": f"Source '{source}' added successfully."} - - -@app.post("/query") -async def handle_query(question_model: QuestionModel): - """ - Handles a query to the EmbedChain app. - Expects a JSON with a "question" key. - """ - question = question_model.question - answer = embedchain_app.query(question) - return {"answer": answer} - - -@app.post("/chat") -async def handle_chat(question_model: QuestionModel): - """ - Handles a chat request to the EmbedChain app. - Expects a JSON with a "question" key. - """ - question = question_model.question - response = embedchain_app.chat(question) - return {"response": response} - - -@app.get("/") -async def root(): - return responses.RedirectResponse(url="/docs") diff --git a/embedchain/examples/nextjs/ec_app/embedchain.json b/embedchain/examples/nextjs/ec_app/embedchain.json deleted file mode 100644 index 91074d5b4..000000000 --- a/embedchain/examples/nextjs/ec_app/embedchain.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "provider": "fly.io" -} \ No newline at end of file diff --git a/embedchain/examples/nextjs/ec_app/fly.toml b/embedchain/examples/nextjs/ec_app/fly.toml deleted file mode 100644 index a622c22d5..000000000 --- a/embedchain/examples/nextjs/ec_app/fly.toml +++ /dev/null @@ -1,22 +0,0 @@ -# fly.toml app configuration file generated for ec-app-crimson-dew-123 on 2024-01-04T06:48:40+05:30 -# -# See https://fly.io/docs/reference/configuration/ for information about how to use this file. -# - -app = "ec-app-crimson-dew-123" -primary_region = "sjc" - -[build] - -[http_service] - internal_port = 8080 - force_https = true - auto_stop_machines = false - auto_start_machines = true - min_machines_running = 0 - processes = ["app"] - -[[vm]] - cpu_kind = "shared" - cpus = 1 - memory_mb = 1024 diff --git a/embedchain/examples/nextjs/ec_app/requirements.txt b/embedchain/examples/nextjs/ec_app/requirements.txt deleted file mode 100644 index 3a7689298..000000000 --- a/embedchain/examples/nextjs/ec_app/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -fastapi==0.104.0 -uvicorn==0.23.2 -embedchain -beautifulsoup4 \ No newline at end of file diff --git a/embedchain/examples/nextjs/nextjs_discord/.dockerignore b/embedchain/examples/nextjs/nextjs_discord/.dockerignore deleted file mode 100644 index 9f4c740db..000000000 --- a/embedchain/examples/nextjs/nextjs_discord/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -db/ \ No newline at end of file diff --git a/embedchain/examples/nextjs/nextjs_discord/.env.example b/embedchain/examples/nextjs/nextjs_discord/.env.example deleted file mode 100644 index 760a08d1b..000000000 --- a/embedchain/examples/nextjs/nextjs_discord/.env.example +++ /dev/null @@ -1,3 +0,0 @@ -DISCORD_BOT_TOKEN=xxxx -DISCORD_BOT_NAME=your_bot_name -EC_APP_URL=your_embedchain_app_url \ No newline at end of file diff --git a/embedchain/examples/nextjs/nextjs_discord/Dockerfile b/embedchain/examples/nextjs/nextjs_discord/Dockerfile deleted file mode 100644 index f151c915b..000000000 --- a/embedchain/examples/nextjs/nextjs_discord/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM python:3.11-slim - -WORKDIR /app - -COPY requirements.txt /app - -RUN pip install -r requirements.txt - -COPY . /app - -CMD ["python", "app.py"] diff --git a/embedchain/examples/nextjs/nextjs_discord/app.py b/embedchain/examples/nextjs/nextjs_discord/app.py deleted file mode 100644 index 74b245aba..000000000 --- a/embedchain/examples/nextjs/nextjs_discord/app.py +++ /dev/null @@ -1,111 +0,0 @@ -import logging -import os - -import discord -import dotenv -import requests - -dotenv.load_dotenv(".env") - -intents = discord.Intents.default() -intents.message_content = True -client = discord.Client(intents=intents) -discord_bot_name = os.environ["DISCORD_BOT_NAME"] - -logger = logging.getLogger(__name__) - - -class NextJSBot: - def __init__(self) -> None: - logger.info("NextJS Bot powered with embedchain.") - - def add(self, _): - raise ValueError("Add is not implemented yet") - - def query(self, message, citations: bool = False): - url = os.environ["EC_APP_URL"] + "/query" - payload = { - "question": message, - "citations": citations, - } - try: - response = requests.request("POST", url, json=payload) - try: - response = response.json() - except Exception: - logger.error(f"Failed to parse response: {response}") - response = {} - return response - except Exception: - logger.exception(f"Failed to query {message}.") - response = "An error occurred. Please try again!" - return response - - def start(self): - discord_token = os.environ["DISCORD_BOT_TOKEN"] - client.run(discord_token) - - -NEXTJS_BOT = NextJSBot() - - -@client.event -async def on_ready(): - logger.info(f"User {client.user.name} logged in with id: {client.user.id}!") - - -def _get_question(message): - user_ids = message.raw_mentions - if len(user_ids) > 0: - for user_id in user_ids: - # remove mentions from message - question = message.content.replace(f"<@{user_id}>", "").strip() - return question - - -async def answer_query(message): - if ( - message.channel.type == discord.ChannelType.public_thread - or message.channel.type == discord.ChannelType.private_thread - ): - await message.channel.send( - "🧵 Currently, we don't support answering questions in threads. Could you please send your message in the channel for a swift response? Appreciate your understanding! 🚀" # noqa: E501 - ) - return - - question = _get_question(message) - print("Answering question: ", question) - thread = await message.create_thread(name=question) - await thread.send("🎭 Putting on my thinking cap, brb with an epic response!") - response = NEXTJS_BOT.query(question, citations=True) - - default_answer = "Sorry, I don't know the answer to that question. Please refer to the documentation.\nhttps://nextjs.org/docs" # noqa: E501 - answer = response.get("answer", default_answer) - - contexts = response.get("contexts", []) - if contexts: - sources = list(set(map(lambda x: x[1]["url"], contexts))) - answer += "\n\n**Sources**:\n" - for i, source in enumerate(sources): - answer += f"- {source}\n" - - sent_message = await thread.send(answer) - await sent_message.add_reaction("😮") - await sent_message.add_reaction("👍") - await sent_message.add_reaction("❤️") - await sent_message.add_reaction("👎") - - -@client.event -async def on_message(message): - mentions = message.mentions - if len(mentions) > 0 and any([user.bot and user.name == discord_bot_name for user in mentions]): - await answer_query(message) - - -def start_bot(): - NEXTJS_BOT.start() - - -if __name__ == "__main__": - start_bot() diff --git a/embedchain/examples/nextjs/nextjs_discord/embedchain.json b/embedchain/examples/nextjs/nextjs_discord/embedchain.json deleted file mode 100644 index 91074d5b4..000000000 --- a/embedchain/examples/nextjs/nextjs_discord/embedchain.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "provider": "fly.io" -} \ No newline at end of file diff --git a/embedchain/examples/nextjs/nextjs_discord/fly.toml b/embedchain/examples/nextjs/nextjs_discord/fly.toml deleted file mode 100644 index 64a5c103f..000000000 --- a/embedchain/examples/nextjs/nextjs_discord/fly.toml +++ /dev/null @@ -1,22 +0,0 @@ -# fly.toml app configuration file generated for nextjs-discord on 2024-01-04T06:56:01+05:30 -# -# See https://fly.io/docs/reference/configuration/ for information about how to use this file. -# - -app = "nextjs-discord" -primary_region = "sjc" - -[build] - -[http_service] - internal_port = 8080 - force_https = true - auto_stop_machines = true - auto_start_machines = true - min_machines_running = 0 - processes = ["app"] - -[[vm]] - cpu_kind = "shared" - cpus = 1 - memory_mb = 1024 diff --git a/embedchain/examples/nextjs/nextjs_discord/requirements.txt b/embedchain/examples/nextjs/nextjs_discord/requirements.txt deleted file mode 100644 index 3a7689298..000000000 --- a/embedchain/examples/nextjs/nextjs_discord/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -fastapi==0.104.0 -uvicorn==0.23.2 -embedchain -beautifulsoup4 \ No newline at end of file diff --git a/embedchain/examples/nextjs/nextjs_slack/.dockerignore b/embedchain/examples/nextjs/nextjs_slack/.dockerignore deleted file mode 100644 index 9f4c740db..000000000 --- a/embedchain/examples/nextjs/nextjs_slack/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -db/ \ No newline at end of file diff --git a/embedchain/examples/nextjs/nextjs_slack/.env.example b/embedchain/examples/nextjs/nextjs_slack/.env.example deleted file mode 100644 index 8b23e52d2..000000000 --- a/embedchain/examples/nextjs/nextjs_slack/.env.example +++ /dev/null @@ -1,3 +0,0 @@ -SLACK_APP_TOKEN=xapp-xxxx -SLACK_BOT_TOKEN=xoxb-xxxx -EC_APP_URL=your_embedchain_app_url \ No newline at end of file diff --git a/embedchain/examples/nextjs/nextjs_slack/Dockerfile b/embedchain/examples/nextjs/nextjs_slack/Dockerfile deleted file mode 100644 index f151c915b..000000000 --- a/embedchain/examples/nextjs/nextjs_slack/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM python:3.11-slim - -WORKDIR /app - -COPY requirements.txt /app - -RUN pip install -r requirements.txt - -COPY . /app - -CMD ["python", "app.py"] diff --git a/embedchain/examples/nextjs/nextjs_slack/app.py b/embedchain/examples/nextjs/nextjs_slack/app.py deleted file mode 100644 index 005a4e29c..000000000 --- a/embedchain/examples/nextjs/nextjs_slack/app.py +++ /dev/null @@ -1,124 +0,0 @@ -import logging -import os -import re - -import requests -from dotenv import load_dotenv -from slack_bolt import App as SlackApp -from slack_bolt.adapter.socket_mode import SocketModeHandler - -load_dotenv(".env") - -logger = logging.getLogger(__name__) - - -def remove_mentions(message): - mention_pattern = re.compile(r"<@[^>]+>") - cleaned_message = re.sub(mention_pattern, "", message) - cleaned_message.strip() - return cleaned_message - - -class SlackBotApp: - def __init__(self) -> None: - logger.info("Slack Bot using Embedchain!") - - def add(self, _): - raise ValueError("Add is not implemented yet") - - def query(self, query, citations: bool = False): - url = os.environ["EC_APP_URL"] + "/query" - payload = { - "question": query, - "citations": citations, - } - try: - response = requests.request("POST", url, json=payload) - try: - response = response.json() - except Exception: - logger.error(f"Failed to parse response: {response}") - response = {} - return response - except Exception: - logger.exception(f"Failed to query {query}.") - response = "An error occurred. Please try again!" - return response - - -SLACK_APP_TOKEN = os.environ["SLACK_APP_TOKEN"] -SLACK_BOT_TOKEN = os.environ["SLACK_BOT_TOKEN"] - -slack_app = SlackApp(token=SLACK_BOT_TOKEN) -slack_bot = SlackBotApp() - - -@slack_app.event("message") -def app_message_handler(message, say): - pass - - -@slack_app.event("app_mention") -def app_mention_handler(body, say, client): - # Get the timestamp of the original message to reply in the thread - if "thread_ts" in body["event"]: - # thread is already created - thread_ts = body["event"]["thread_ts"] - say( - text="🧵 Currently, we don't support answering questions in threads. Could you please send your message in the channel for a swift response? Appreciate your understanding! 🚀", # noqa: E501 - thread_ts=thread_ts, - ) - return - - thread_ts = body["event"]["ts"] - say( - text="🎭 Putting on my thinking cap, brb with an epic response!", - thread_ts=thread_ts, - ) - query = body["event"]["text"] - question = remove_mentions(query) - print("Asking question: ", question) - response = slack_bot.query(question, citations=True) - default_answer = "Sorry, I don't know the answer to that question. Please refer to the documentation.\nhttps://nextjs.org/docs" # noqa: E501 - answer = response.get("answer", default_answer) - contexts = response.get("contexts", []) - if contexts: - sources = list(set(map(lambda x: x[1]["url"], contexts))) - answer += "\n\n*Sources*:\n" - for i, source in enumerate(sources): - answer += f"- {source}\n" - - print("Sending answer: ", answer) - result = say(text=answer, thread_ts=thread_ts) - if result["ok"]: - channel = result["channel"] - timestamp = result["ts"] - client.reactions_add( - channel=channel, - name="open_mouth", - timestamp=timestamp, - ) - client.reactions_add( - channel=channel, - name="thumbsup", - timestamp=timestamp, - ) - client.reactions_add( - channel=channel, - name="heart", - timestamp=timestamp, - ) - client.reactions_add( - channel=channel, - name="thumbsdown", - timestamp=timestamp, - ) - - -def start_bot(): - slack_socket_mode_handler = SocketModeHandler(slack_app, SLACK_APP_TOKEN) - slack_socket_mode_handler.start() - - -if __name__ == "__main__": - start_bot() diff --git a/embedchain/examples/nextjs/nextjs_slack/embedchain.json b/embedchain/examples/nextjs/nextjs_slack/embedchain.json deleted file mode 100644 index 91074d5b4..000000000 --- a/embedchain/examples/nextjs/nextjs_slack/embedchain.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "provider": "fly.io" -} \ No newline at end of file diff --git a/embedchain/examples/nextjs/nextjs_slack/fly.toml b/embedchain/examples/nextjs/nextjs_slack/fly.toml deleted file mode 100644 index ca278bcd8..000000000 --- a/embedchain/examples/nextjs/nextjs_slack/fly.toml +++ /dev/null @@ -1,22 +0,0 @@ -# fly.toml app configuration file generated for nextjs-slack on 2024-01-05T09:33:59+05:30 -# -# See https://fly.io/docs/reference/configuration/ for information about how to use this file. -# - -app = "nextjs-slack" -primary_region = "sjc" - -[build] - -[http_service] - internal_port = 8080 - force_https = true - auto_stop_machines = false - auto_start_machines = true - min_machines_running = 0 - processes = ["app"] - -[[vm]] - cpu_kind = "shared" - cpus = 1 - memory_mb = 1024 diff --git a/embedchain/examples/nextjs/nextjs_slack/requirements.txt b/embedchain/examples/nextjs/nextjs_slack/requirements.txt deleted file mode 100644 index da5e1e4d4..000000000 --- a/embedchain/examples/nextjs/nextjs_slack/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -python-dotenv -slack-sdk -slack_bolt -embedchain \ No newline at end of file diff --git a/embedchain/examples/nextjs/requirements.txt b/embedchain/examples/nextjs/requirements.txt deleted file mode 100644 index b245d1f0f..000000000 --- a/embedchain/examples/nextjs/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -fastapi==0.104.0 -uvicorn==0.23.2 -embedchain[opensource] -beautifulsoup4 -discord -python-dotenv -slack-sdk -slack_bolt diff --git a/embedchain/examples/private-ai/README.md b/embedchain/examples/private-ai/README.md deleted file mode 100644 index c0739ced8..000000000 --- a/embedchain/examples/private-ai/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Private AI - -In this example, we will create a private AI using embedchain. - -Private AI is useful when you want to chat with your data and you dont want to spend money and your data should stay on your machine. - -## How to install - -First create a virtual environment and install the requirements by running - -```bash -pip install -r requirements.txt -``` - -## How to use - -* Now open privateai.py file and change the line `app.add` to point to your directory or data source. -* If you want to add any other data type, you can browse the supported data types [here](https://docs.embedchain.ai/components/data-sources/overview) - -* Now simply run the file by - -```bash -python privateai.py -``` - -* Now you can enter and ask any questions from your data. \ No newline at end of file diff --git a/embedchain/examples/private-ai/config.yaml b/embedchain/examples/private-ai/config.yaml deleted file mode 100644 index bc243f340..000000000 --- a/embedchain/examples/private-ai/config.yaml +++ /dev/null @@ -1,10 +0,0 @@ -llm: - provider: gpt4all - config: - model: 'orca-mini-3b-gguf2-q4_0.gguf' - max_tokens: 1000 - top_p: 1 -embedder: - provider: huggingface - config: - model: 'sentence-transformers/all-MiniLM-L6-v2' \ No newline at end of file diff --git a/embedchain/examples/private-ai/privateai.py b/embedchain/examples/private-ai/privateai.py deleted file mode 100644 index 613bc2a16..000000000 --- a/embedchain/examples/private-ai/privateai.py +++ /dev/null @@ -1,15 +0,0 @@ -from embedchain import App - -app = App.from_config("config.yaml") -app.add("/path/to/your/folder", data_type="directory") - -while True: - user_input = input("Enter your question (type 'exit' to quit): ") - - # Break the loop if the user types 'exit' - if user_input.lower() == "exit": - break - - # Process the input and provide a response - response = app.chat(user_input) - print(response) diff --git a/embedchain/examples/private-ai/requirements.txt b/embedchain/examples/private-ai/requirements.txt deleted file mode 100644 index 3ad57c3a3..000000000 --- a/embedchain/examples/private-ai/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -"embedchain[opensource]" \ No newline at end of file diff --git a/embedchain/examples/rest-api/.dockerignore b/embedchain/examples/rest-api/.dockerignore deleted file mode 100644 index 9d8eb1ab0..000000000 --- a/embedchain/examples/rest-api/.dockerignore +++ /dev/null @@ -1,4 +0,0 @@ -.env -app.db -configs/**.yaml -db \ No newline at end of file diff --git a/embedchain/examples/rest-api/.gitignore b/embedchain/examples/rest-api/.gitignore deleted file mode 100644 index 60d5cd374..000000000 --- a/embedchain/examples/rest-api/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.env -app.db -configs/**.yaml -db diff --git a/embedchain/examples/rest-api/Dockerfile b/embedchain/examples/rest-api/Dockerfile deleted file mode 100644 index fe36d4adb..000000000 --- a/embedchain/examples/rest-api/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM python:3.11-slim - -WORKDIR /app - -COPY requirements.txt /app/ - -RUN pip install --no-cache-dir -r requirements.txt - -COPY . /app - -EXPOSE 8080 - -ENV NAME embedchain - -CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"] diff --git a/embedchain/examples/rest-api/README.md b/embedchain/examples/rest-api/README.md deleted file mode 100644 index 4a20af78b..000000000 --- a/embedchain/examples/rest-api/README.md +++ /dev/null @@ -1,21 +0,0 @@ -## Single command to rule them all, - -```bash -docker run -d --name embedchain -p 8080:8080 embedchain/rest-api:latest -``` - -### To run the app locally, - -```bash -# will help reload on changes -DEVELOPMENT=True && python -m main -``` - -Using docker (locally), - -```bash -docker build -t embedchain/rest-api:latest . -docker run -d --name embedchain -p 8080:8080 embedchain/rest-api:latest -docker image push embedchain/rest-api:latest -``` - diff --git a/embedchain/examples/rest-api/__init__.py b/embedchain/examples/rest-api/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/examples/rest-api/bruno/ec-rest-api/bruno.json b/embedchain/examples/rest-api/bruno/ec-rest-api/bruno.json deleted file mode 100644 index ed86683c3..000000000 --- a/embedchain/examples/rest-api/bruno/ec-rest-api/bruno.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "version": "1", - "name": "ec-rest-api", - "type": "collection" -} \ No newline at end of file diff --git a/embedchain/examples/rest-api/bruno/ec-rest-api/default_add.bru b/embedchain/examples/rest-api/bruno/ec-rest-api/default_add.bru deleted file mode 100644 index 1cd0144ba..000000000 --- a/embedchain/examples/rest-api/bruno/ec-rest-api/default_add.bru +++ /dev/null @@ -1,18 +0,0 @@ -meta { - name: default_add - type: http - seq: 3 -} - -post { - url: http://localhost:8080/add - body: json - auth: none -} - -body:json { - { - "source": "source_url", - "data_type": "data_type" - } -} diff --git a/embedchain/examples/rest-api/bruno/ec-rest-api/default_chat.bru b/embedchain/examples/rest-api/bruno/ec-rest-api/default_chat.bru deleted file mode 100644 index 4c4cbced4..000000000 --- a/embedchain/examples/rest-api/bruno/ec-rest-api/default_chat.bru +++ /dev/null @@ -1,17 +0,0 @@ -meta { - name: default_chat - type: http - seq: 4 -} - -post { - url: http://localhost:8080/chat - body: json - auth: none -} - -body:json { - { - "message": "message" - } -} diff --git a/embedchain/examples/rest-api/bruno/ec-rest-api/default_query.bru b/embedchain/examples/rest-api/bruno/ec-rest-api/default_query.bru deleted file mode 100644 index 61e55c6bd..000000000 --- a/embedchain/examples/rest-api/bruno/ec-rest-api/default_query.bru +++ /dev/null @@ -1,17 +0,0 @@ -meta { - name: default_query - type: http - seq: 2 -} - -post { - url: http://localhost:8080/query - body: json - auth: none -} - -body:json { - { - "query": "Who is Elon Musk?" - } -} diff --git a/embedchain/examples/rest-api/bruno/ec-rest-api/ping.bru b/embedchain/examples/rest-api/bruno/ec-rest-api/ping.bru deleted file mode 100644 index 22128827d..000000000 --- a/embedchain/examples/rest-api/bruno/ec-rest-api/ping.bru +++ /dev/null @@ -1,11 +0,0 @@ -meta { - name: ping - type: http - seq: 1 -} - -get { - url: http://localhost:8080/ping - body: json - auth: none -} diff --git a/embedchain/examples/rest-api/configs/README.md b/embedchain/examples/rest-api/configs/README.md deleted file mode 100644 index bf4bbc9ee..000000000 --- a/embedchain/examples/rest-api/configs/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Config directory - -Here, all the YAML files will get stored. diff --git a/embedchain/examples/rest-api/database.py b/embedchain/examples/rest-api/database.py deleted file mode 100644 index 3eaafc95c..000000000 --- a/embedchain/examples/rest-api/database.py +++ /dev/null @@ -1,11 +0,0 @@ -from sqlalchemy import create_engine -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.orm import sessionmaker - -SQLALCHEMY_DATABASE_URI = "sqlite:///./app.db" - -engine = create_engine(SQLALCHEMY_DATABASE_URI, connect_args={"check_same_thread": False}) - -SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) - -Base = declarative_base() diff --git a/embedchain/examples/rest-api/default.yaml b/embedchain/examples/rest-api/default.yaml deleted file mode 100644 index bcdcf53f9..000000000 --- a/embedchain/examples/rest-api/default.yaml +++ /dev/null @@ -1,17 +0,0 @@ -app: - config: - id: 'default' - -llm: - provider: gpt4all - config: - model: 'orca-mini-3b-gguf2-q4_0.gguf' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -embedder: - provider: gpt4all - config: - model: 'all-MiniLM-L6-v2' diff --git a/embedchain/examples/rest-api/main.py b/embedchain/examples/rest-api/main.py deleted file mode 100644 index 66eef9276..000000000 --- a/embedchain/examples/rest-api/main.py +++ /dev/null @@ -1,326 +0,0 @@ -import logging -import os - -import aiofiles -import yaml -from database import Base, SessionLocal, engine -from fastapi import Depends, FastAPI, HTTPException, UploadFile -from models import DefaultResponse, DeployAppRequest, QueryApp, SourceApp -from services import get_app, get_apps, remove_app, save_app -from sqlalchemy.orm import Session -from utils import generate_error_message_for_api_keys - -from embedchain import App -from embedchain.client import Client - -logger = logging.getLogger(__name__) - -Base.metadata.create_all(bind=engine) - - -def get_db(): - db = SessionLocal() - try: - yield db - finally: - db.close() - - -app = FastAPI( - title="Embedchain REST API", - description="This is the REST API for Embedchain.", - version="0.0.1", - license_info={ - "name": "Apache 2.0", - "url": "https://github.com/embedchain/embedchain/blob/main/LICENSE", - }, -) - - -@app.get("/ping", tags=["Utility"]) -def check_status(): - """ - Endpoint to check the status of the API - """ - return {"ping": "pong"} - - -@app.get("/apps", tags=["Apps"]) -async def get_all_apps(db: Session = Depends(get_db)): - """ - Get all apps. - """ - apps = get_apps(db) - return {"results": apps} - - -@app.post("/create", tags=["Apps"], response_model=DefaultResponse) -async def create_app_using_default_config(app_id: str, config: UploadFile = None, db: Session = Depends(get_db)): - """ - Create a new app using App ID. - If you don't provide a config file, Embedchain will use the default config file\n - which uses opensource GPT4ALL model.\n - app_id: The ID of the app.\n - config: The YAML config file to create an App.\n - """ - try: - if app_id is None: - raise HTTPException(detail="App ID not provided.", status_code=400) - - if get_app(db, app_id) is not None: - raise HTTPException(detail=f"App with id '{app_id}' already exists.", status_code=400) - - yaml_path = "default.yaml" - if config is not None: - contents = await config.read() - try: - yaml.safe_load(contents) - # TODO: validate the config yaml file here - yaml_path = f"configs/{app_id}.yaml" - async with aiofiles.open(yaml_path, mode="w") as file_out: - await file_out.write(str(contents, "utf-8")) - except yaml.YAMLError as exc: - raise HTTPException(detail=f"Error parsing YAML: {exc}", status_code=400) - - save_app(db, app_id, yaml_path) - - return DefaultResponse(response=f"App created successfully. App ID: {app_id}") - except Exception as e: - logger.warning(str(e)) - raise HTTPException(detail=f"Error creating app: {str(e)}", status_code=400) - - -@app.get( - "/{app_id}/data", - tags=["Apps"], -) -async def get_datasources_associated_with_app_id(app_id: str, db: Session = Depends(get_db)): - """ - Get all data sources for an app.\n - app_id: The ID of the app. Use "default" for the default app.\n - """ - try: - if app_id is None: - raise HTTPException( - detail="App ID not provided. If you want to use the default app, use 'default' as the app_id.", - status_code=400, - ) - - db_app = get_app(db, app_id) - - if db_app is None: - raise HTTPException(detail=f"App with id {app_id} does not exist, please create it first.", status_code=400) - - app = App.from_config(config_path=db_app.config) - - response = app.get_data_sources() - return {"results": response} - except ValueError as ve: - logger.warning(str(ve)) - raise HTTPException( - detail=generate_error_message_for_api_keys(ve), - status_code=400, - ) - except Exception as e: - logger.warning(str(e)) - raise HTTPException(detail=f"Error occurred: {str(e)}", status_code=400) - - -@app.post( - "/{app_id}/add", - tags=["Apps"], - response_model=DefaultResponse, -) -async def add_datasource_to_an_app(body: SourceApp, app_id: str, db: Session = Depends(get_db)): - """ - Add a source to an existing app.\n - app_id: The ID of the app. Use "default" for the default app.\n - source: The source to add.\n - data_type: The data type of the source. Remove it if you want Embedchain to detect it automatically.\n - """ - try: - if app_id is None: - raise HTTPException( - detail="App ID not provided. If you want to use the default app, use 'default' as the app_id.", - status_code=400, - ) - - db_app = get_app(db, app_id) - - if db_app is None: - raise HTTPException(detail=f"App with id {app_id} does not exist, please create it first.", status_code=400) - - app = App.from_config(config_path=db_app.config) - - response = app.add(source=body.source, data_type=body.data_type) - return DefaultResponse(response=response) - except ValueError as ve: - logger.warning(str(ve)) - raise HTTPException( - detail=generate_error_message_for_api_keys(ve), - status_code=400, - ) - except Exception as e: - logger.warning(str(e)) - raise HTTPException(detail=f"Error occurred: {str(e)}", status_code=400) - - -@app.post( - "/{app_id}/query", - tags=["Apps"], - response_model=DefaultResponse, -) -async def query_an_app(body: QueryApp, app_id: str, db: Session = Depends(get_db)): - """ - Query an existing app.\n - app_id: The ID of the app. Use "default" for the default app.\n - query: The query that you want to ask the App.\n - """ - try: - if app_id is None: - raise HTTPException( - detail="App ID not provided. If you want to use the default app, use 'default' as the app_id.", - status_code=400, - ) - - db_app = get_app(db, app_id) - - if db_app is None: - raise HTTPException(detail=f"App with id {app_id} does not exist, please create it first.", status_code=400) - - app = App.from_config(config_path=db_app.config) - - response = app.query(body.query) - return DefaultResponse(response=response) - except ValueError as ve: - logger.warning(str(ve)) - raise HTTPException( - detail=generate_error_message_for_api_keys(ve), - status_code=400, - ) - except Exception as e: - logger.warning(str(e)) - raise HTTPException(detail=f"Error occurred: {str(e)}", status_code=400) - - -# FIXME: The chat implementation of Embedchain needs to be modified to work with the REST API. -# @app.post( -# "/{app_id}/chat", -# tags=["Apps"], -# response_model=DefaultResponse, -# ) -# async def chat_with_an_app(body: MessageApp, app_id: str, db: Session = Depends(get_db)): -# """ -# Query an existing app.\n -# app_id: The ID of the app. Use "default" for the default app.\n -# message: The message that you want to send to the App.\n -# """ -# try: -# if app_id is None: -# raise HTTPException( -# detail="App ID not provided. If you want to use the default app, use 'default' as the app_id.", -# status_code=400, -# ) - -# db_app = get_app(db, app_id) - -# if db_app is None: -# raise HTTPException( -# detail=f"App with id {app_id} does not exist, please create it first.", -# status_code=400 -# ) - -# app = App.from_config(config_path=db_app.config) - -# response = app.chat(body.message) -# return DefaultResponse(response=response) -# except ValueError as ve: -# raise HTTPException( -# detail=generate_error_message_for_api_keys(ve), -# status_code=400, -# ) -# except Exception as e: -# raise HTTPException(detail=f"Error occurred: {str(e)}", status_code=400) - - -@app.post( - "/{app_id}/deploy", - tags=["Apps"], - response_model=DefaultResponse, -) -async def deploy_app(body: DeployAppRequest, app_id: str, db: Session = Depends(get_db)): - """ - Query an existing app.\n - app_id: The ID of the app. Use "default" for the default app.\n - api_key: The API key to use for deployment. If not provided, - Embedchain will use the API key previously used (if any).\n - """ - try: - if app_id is None: - raise HTTPException( - detail="App ID not provided. If you want to use the default app, use 'default' as the app_id.", - status_code=400, - ) - - db_app = get_app(db, app_id) - - if db_app is None: - raise HTTPException(detail=f"App with id {app_id} does not exist, please create it first.", status_code=400) - - app = App.from_config(config_path=db_app.config) - - api_key = body.api_key - # this will save the api key in the embedchain.db - Client(api_key=api_key) - - app.deploy() - return DefaultResponse(response="App deployed successfully.") - except ValueError as ve: - logger.warning(str(ve)) - raise HTTPException( - detail=generate_error_message_for_api_keys(ve), - status_code=400, - ) - except Exception as e: - logger.warning(str(e)) - raise HTTPException(detail=f"Error occurred: {str(e)}", status_code=400) - - -@app.delete( - "/{app_id}/delete", - tags=["Apps"], - response_model=DefaultResponse, -) -async def delete_app(app_id: str, db: Session = Depends(get_db)): - """ - Delete an existing app.\n - app_id: The ID of the app to be deleted. - """ - try: - if app_id is None: - raise HTTPException( - detail="App ID not provided. If you want to use the default app, use 'default' as the app_id.", - status_code=400, - ) - - db_app = get_app(db, app_id) - - if db_app is None: - raise HTTPException(detail=f"App with id {app_id} does not exist, please create it first.", status_code=400) - - app = App.from_config(config_path=db_app.config) - - # reset app.db - app.db.reset() - - remove_app(db, app_id) - return DefaultResponse(response=f"App with id {app_id} deleted successfully.") - except Exception as e: - raise HTTPException(detail=f"Error occurred: {str(e)}", status_code=400) - - -if __name__ == "__main__": - import uvicorn - - is_dev = os.getenv("DEVELOPMENT", "False") - uvicorn.run("main:app", host="0.0.0.0", port=8080, reload=bool(is_dev)) diff --git a/embedchain/examples/rest-api/models.py b/embedchain/examples/rest-api/models.py deleted file mode 100644 index 1aecf00aa..000000000 --- a/embedchain/examples/rest-api/models.py +++ /dev/null @@ -1,46 +0,0 @@ -from typing import Optional - -from database import Base -from pydantic import BaseModel, Field -from sqlalchemy import Column, Integer, String - - -class QueryApp(BaseModel): - query: str = Field("", description="The query that you want to ask the App.") - - model_config = { - "json_schema_extra": { - "example": { - "query": "Who is Elon Musk?", - } - } - } - - -class SourceApp(BaseModel): - source: str = Field("", description="The source that you want to add to the App.") - data_type: Optional[str] = Field("", description="The type of data to add, remove it for autosense.") - - model_config = {"json_schema_extra": {"example": {"source": "https://en.wikipedia.org/wiki/Elon_Musk"}}} - - -class DeployAppRequest(BaseModel): - api_key: str = Field("", description="The Embedchain API key for App deployments.") - - model_config = {"json_schema_extra": {"example": {"api_key": "ec-xxx"}}} - - -class MessageApp(BaseModel): - message: str = Field("", description="The message that you want to send to the App.") - - -class DefaultResponse(BaseModel): - response: str - - -class AppModel(Base): - __tablename__ = "apps" - - id = Column(Integer, primary_key=True, index=True) - app_id = Column(String, unique=True, index=True) - config = Column(String, unique=True, index=True) diff --git a/embedchain/examples/rest-api/requirements.txt b/embedchain/examples/rest-api/requirements.txt deleted file mode 100644 index 5c18f35bb..000000000 --- a/embedchain/examples/rest-api/requirements.txt +++ /dev/null @@ -1,24 +0,0 @@ -fastapi==0.104.0 -uvicorn==0.23.2 -streamlit==1.29.0 -embedchain==0.1.57 -slack-sdk==3.21.3 -flask==2.3.3 -fastapi-poe==0.0.16 -discord==2.3.2 -twilio==8.5.0 -huggingface-hub==0.17.3 -embedchain[community, opensource, elasticsearch, opensearch, weaviate, pinecone, qdrant, images, cohere, together, milvus, vertexai, llama2, gmail, json]==0.1.57 -sqlalchemy==2.0.22 -python-multipart==0.0.6 -youtube-transcript-api==0.6.1 -pytube==15.0.0 -beautifulsoup4==4.12.3 -slack-sdk==3.21.3 -huggingface_hub==0.23.0 -gitpython==3.1.38 -yt_dlp==2023.11.14 -PyGithub==1.59.1 -feedparser==6.0.10 -newspaper3k==0.2.8 -listparser==0.19 \ No newline at end of file diff --git a/embedchain/examples/rest-api/sample-config.yaml b/embedchain/examples/rest-api/sample-config.yaml deleted file mode 100644 index c7b867e41..000000000 --- a/embedchain/examples/rest-api/sample-config.yaml +++ /dev/null @@ -1,33 +0,0 @@ -app: - config: - id: 'default-app' - -llm: - provider: openai - config: - model: 'gpt-4o-mini' - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - template: | - Use the following pieces of context to answer the query at the end. - If you don't know the answer, just say that you don't know, don't try to make up an answer. - - $context - - Query: $query - - Helpful Answer: - -vectordb: - provider: chroma - config: - collection_name: 'rest-api-app' - dir: db - allow_reset: true - -embedder: - provider: openai - config: - model: 'text-embedding-ada-002' diff --git a/embedchain/examples/rest-api/services.py b/embedchain/examples/rest-api/services.py deleted file mode 100644 index c200454b8..000000000 --- a/embedchain/examples/rest-api/services.py +++ /dev/null @@ -1,25 +0,0 @@ -from models import AppModel -from sqlalchemy.orm import Session - - -def get_app(db: Session, app_id: str): - return db.query(AppModel).filter(AppModel.app_id == app_id).first() - - -def get_apps(db: Session, skip: int = 0, limit: int = 100): - return db.query(AppModel).offset(skip).limit(limit).all() - - -def save_app(db: Session, app_id: str, config: str): - db_app = AppModel(app_id=app_id, config=config) - db.add(db_app) - db.commit() - db.refresh(db_app) - return db_app - - -def remove_app(db: Session, app_id: str): - db_app = db.query(AppModel).filter(AppModel.app_id == app_id).first() - db.delete(db_app) - db.commit() - return db_app diff --git a/embedchain/examples/rest-api/utils.py b/embedchain/examples/rest-api/utils.py deleted file mode 100644 index ca41bed45..000000000 --- a/embedchain/examples/rest-api/utils.py +++ /dev/null @@ -1,22 +0,0 @@ -def generate_error_message_for_api_keys(error: ValueError) -> str: - env_mapping = { - "OPENAI_API_KEY": "OPENAI_API_KEY", - "OPENAI_API_TYPE": "OPENAI_API_TYPE", - "OPENAI_API_BASE": "OPENAI_API_BASE", - "OPENAI_API_VERSION": "OPENAI_API_VERSION", - "COHERE_API_KEY": "COHERE_API_KEY", - "TOGETHER_API_KEY": "TOGETHER_API_KEY", - "ANTHROPIC_API_KEY": "ANTHROPIC_API_KEY", - "JINACHAT_API_KEY": "JINACHAT_API_KEY", - "HUGGINGFACE_ACCESS_TOKEN": "HUGGINGFACE_ACCESS_TOKEN", - "REPLICATE_API_TOKEN": "REPLICATE_API_TOKEN", - } - - missing_keys = [env_mapping[key] for key in env_mapping if key in str(error)] - if missing_keys: - missing_keys_str = ", ".join(missing_keys) - return f"""Please set the {missing_keys_str} environment variable(s) when running the Docker container. -Example: `docker run -e {missing_keys[0]}=xxx embedchain/rest-api:latest` -""" - else: - return "Error: " + str(error) diff --git a/embedchain/examples/sadhguru-ai/README.md b/embedchain/examples/sadhguru-ai/README.md deleted file mode 100644 index e6ba224b2..000000000 --- a/embedchain/examples/sadhguru-ai/README.md +++ /dev/null @@ -1,19 +0,0 @@ -## Sadhguru AI - -This directory contains the code used to implement [Sadhguru AI](https://sadhguru-ai.streamlit.app/) using Embedchain. It is built on 3K+ videos and 1K+ articles of Sadhguru. You can find the full list of data sources [here](https://gist.github.com/deshraj/50b0597157e04829bbbb7bc418be6ccb). - -## Run locally - -You can run Sadhguru AI locally as a streamlit app using the following command: - -```bash -export OPENAI_API_KEY=sk-xxx -pip install -r requirements.txt -streamlit run app.py -``` - -Note: Remember to set your `OPENAI_API_KEY`. - -## Deploy to production - -You can create your own Sadhguru AI or similar RAG applications in production using one of the several deployment methods provided in [our docs](https://docs.embedchain.ai/get-started/deployment). diff --git a/embedchain/examples/sadhguru-ai/app.py b/embedchain/examples/sadhguru-ai/app.py deleted file mode 100644 index 5c123d600..000000000 --- a/embedchain/examples/sadhguru-ai/app.py +++ /dev/null @@ -1,100 +0,0 @@ -import csv -import queue -import threading -from io import StringIO - -import requests -import streamlit as st - -from embedchain import App -from embedchain.config import BaseLlmConfig -from embedchain.helpers.callbacks import StreamingStdOutCallbackHandlerYield, generate - - -@st.cache_resource -def sadhguru_ai(): - app = App() - return app - - -# Function to read the CSV file row by row -def read_csv_row_by_row(file_path): - with open(file_path, mode="r", newline="", encoding="utf-8") as file: - csv_reader = csv.DictReader(file) - for row in csv_reader: - yield row - - -@st.cache_resource -def add_data_to_app(): - app = sadhguru_ai() - url = "https://gist.githubusercontent.com/deshraj/50b0597157e04829bbbb7bc418be6ccb/raw/95b0f1547028c39691f5c7db04d362baa597f3f4/data.csv" # noqa:E501 - response = requests.get(url) - csv_file = StringIO(response.text) - for row in csv.reader(csv_file): - if row and row[0] != "url": - app.add(row[0], data_type="web_page") - - -app = sadhguru_ai() -add_data_to_app() - -assistant_avatar_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/2/21/Sadhguru-Jaggi-Vasudev.jpg/640px-Sadhguru-Jaggi-Vasudev.jpg" # noqa: E501 - - -st.title("🙏 Sadhguru AI") - -styled_caption = '

🚀 An Embedchain app powered with Sadhguru\'s wisdom!

' # noqa: E501 -st.markdown(styled_caption, unsafe_allow_html=True) # noqa: E501 - -if "messages" not in st.session_state: - st.session_state.messages = [ - { - "role": "assistant", - "content": """ - Hi, I'm Sadhguru AI! I'm a mystic, yogi, visionary, and spiritual master. I'm here to answer your questions about life, the universe, and everything. - """, # noqa: E501 - } - ] - -for message in st.session_state.messages: - role = message["role"] - with st.chat_message(role, avatar=assistant_avatar_url if role == "assistant" else None): - st.markdown(message["content"]) - -if prompt := st.chat_input("Ask me anything!"): - with st.chat_message("user"): - st.markdown(prompt) - st.session_state.messages.append({"role": "user", "content": prompt}) - - with st.chat_message("assistant", avatar=assistant_avatar_url): - msg_placeholder = st.empty() - msg_placeholder.markdown("Thinking...") - full_response = "" - - q = queue.Queue() - - def app_response(result): - config = BaseLlmConfig(stream=True, callbacks=[StreamingStdOutCallbackHandlerYield(q)]) - answer, citations = app.chat(prompt, config=config, citations=True) - result["answer"] = answer - result["citations"] = citations - - results = {} - thread = threading.Thread(target=app_response, args=(results,)) - thread.start() - - for answer_chunk in generate(q): - full_response += answer_chunk - msg_placeholder.markdown(full_response) - - thread.join() - answer, citations = results["answer"], results["citations"] - if citations: - full_response += "\n\n**Sources**:\n" - sources = list(set(map(lambda x: x[1]["url"], citations))) - for i, source in enumerate(sources): - full_response += f"{i+1}. {source}\n" - - msg_placeholder.markdown(full_response) - st.session_state.messages.append({"role": "assistant", "content": full_response}) diff --git a/embedchain/examples/sadhguru-ai/requirements.txt b/embedchain/examples/sadhguru-ai/requirements.txt deleted file mode 100644 index bba32905a..000000000 --- a/embedchain/examples/sadhguru-ai/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -embedchain -streamlit -pysqlite3-binary \ No newline at end of file diff --git a/embedchain/examples/slack_bot/Dockerfile b/embedchain/examples/slack_bot/Dockerfile deleted file mode 100644 index 1b07f204b..000000000 --- a/embedchain/examples/slack_bot/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM python:3.11-slim - -WORKDIR /usr/src/ -COPY requirements.txt . -RUN pip install -r requirements.txt - -COPY . . - -EXPOSE 8000 - -CMD ["python", "-m", "embedchain.bots.slack", "--port", "8000"] diff --git a/embedchain/examples/slack_bot/requirements.txt b/embedchain/examples/slack_bot/requirements.txt deleted file mode 100644 index af7258c94..000000000 --- a/embedchain/examples/slack_bot/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -slack-sdk==3.21.3 -flask==2.3.3 -fastapi-poe==0.0.16 \ No newline at end of file diff --git a/embedchain/examples/telegram_bot/.env.example b/embedchain/examples/telegram_bot/.env.example deleted file mode 100644 index cd80d5eff..000000000 --- a/embedchain/examples/telegram_bot/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -TELEGRAM_BOT_TOKEN= -OPENAI_API_KEY= diff --git a/embedchain/examples/telegram_bot/.gitignore b/embedchain/examples/telegram_bot/.gitignore deleted file mode 100644 index ba288ed39..000000000 --- a/embedchain/examples/telegram_bot/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -__pycache__ -db -database -pyenv -venv -.env -trash_files/ diff --git a/embedchain/examples/telegram_bot/Dockerfile b/embedchain/examples/telegram_bot/Dockerfile deleted file mode 100644 index aed7b62eb..000000000 --- a/embedchain/examples/telegram_bot/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM python:3.11-slim - -WORKDIR /usr/src/ -COPY requirements.txt . -RUN pip install -r requirements.txt - -COPY . . - -EXPOSE 8000 - -CMD ["python", "telegram_bot.py"] diff --git a/embedchain/examples/telegram_bot/README.md b/embedchain/examples/telegram_bot/README.md deleted file mode 100644 index 21fc2df50..000000000 --- a/embedchain/examples/telegram_bot/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Telegram Bot - -This is a replit template to create your own Telegram bot using the embedchain package. To know more about the bot and how to use it, go [here](https://docs.embedchain.ai/examples/telegram_bot). \ No newline at end of file diff --git a/embedchain/examples/telegram_bot/requirements.txt b/embedchain/examples/telegram_bot/requirements.txt deleted file mode 100644 index 3f6614632..000000000 --- a/embedchain/examples/telegram_bot/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -flask==2.3.2 -requests==2.31.0 -python-dotenv==1.0.0 -embedchain \ No newline at end of file diff --git a/embedchain/examples/telegram_bot/telegram_bot.py b/embedchain/examples/telegram_bot/telegram_bot.py deleted file mode 100644 index 8ff8892b3..000000000 --- a/embedchain/examples/telegram_bot/telegram_bot.py +++ /dev/null @@ -1,66 +0,0 @@ -import os - -import requests -from dotenv import load_dotenv -from flask import Flask, request - -from embedchain import App - -app = Flask(__name__) -load_dotenv() -bot_token = os.environ["TELEGRAM_BOT_TOKEN"] -chat_bot = App() - - -@app.route("/", methods=["POST"]) -def telegram_webhook(): - data = request.json - message = data["message"] - chat_id = message["chat"]["id"] - text = message["text"] - if text.startswith("/start"): - response_text = ( - "Welcome to Embedchain Bot! Try the following commands to use the bot:\n" - "For adding data sources:\n /add \n" - "For asking queries:\n /query " - ) - elif text.startswith("/add"): - _, data_type, url_or_text = text.split(maxsplit=2) - response_text = add_to_chat_bot(data_type, url_or_text) - elif text.startswith("/query"): - _, question = text.split(maxsplit=1) - response_text = query_chat_bot(question) - else: - response_text = "Invalid command. Please refer to the documentation for correct syntax." - send_message(chat_id, response_text) - return "OK" - - -def add_to_chat_bot(data_type, url_or_text): - try: - chat_bot.add(data_type, url_or_text) - response_text = f"Added {data_type} : {url_or_text}" - except Exception as e: - response_text = f"Failed to add {data_type} : {url_or_text}" - print("Error occurred during 'add' command:", e) - return response_text - - -def query_chat_bot(question): - try: - response = chat_bot.chat(question) - response_text = response - except Exception as e: - response_text = "An error occurred. Please try again!" - print("Error occurred during 'query' command:", e) - return response_text - - -def send_message(chat_id, text): - url = f"https://api.telegram.org/bot{bot_token}/sendMessage" - data = {"chat_id": chat_id, "text": text} - requests.post(url, json=data) - - -if __name__ == "__main__": - app.run(host="0.0.0.0", port=8000, debug=False) diff --git a/embedchain/examples/unacademy-ai/README.md b/embedchain/examples/unacademy-ai/README.md deleted file mode 100644 index 013f0322f..000000000 --- a/embedchain/examples/unacademy-ai/README.md +++ /dev/null @@ -1,19 +0,0 @@ -## Unacademy UPSC AI - -This directory contains the code used to implement [Unacademy UPSC AI](https://unacademy-ai.streamlit.app/) using Embedchain. It is built on 16K+ youtube videos and 800+ course pages from Unacademy website. You can find the full list of data sources [here](https://gist.github.com/deshraj/7714feadccca13cefe574951652fa9b2). - -## Run locally - -You can run Unacademy AI locally as a streamlit app using the following command: - -```bash -export OPENAI_API_KEY=sk-xxx -pip install -r requirements.txt -streamlit run app.py -``` - -Note: Remember to set your `OPENAI_API_KEY`. - -## Deploy to production - -You can create your own Unacademy AI or similar RAG applications in production using one of the several deployment methods provided in [our docs](https://docs.embedchain.ai/get-started/deployment). diff --git a/embedchain/examples/unacademy-ai/app.py b/embedchain/examples/unacademy-ai/app.py deleted file mode 100644 index e31dba918..000000000 --- a/embedchain/examples/unacademy-ai/app.py +++ /dev/null @@ -1,104 +0,0 @@ -import queue - -import streamlit as st - -from embedchain import App -from embedchain.config import BaseLlmConfig -from embedchain.helpers.callbacks import StreamingStdOutCallbackHandlerYield, generate - - -@st.cache_resource -def unacademy_ai(): - app = App() - return app - - -app = unacademy_ai() - -assistant_avatar_url = "https://cdn-images-1.medium.com/v2/resize:fit:1200/1*LdFNhpOe7uIn-bHK9VUinA.jpeg" - -st.markdown(f"# Unacademy UPSC AI", unsafe_allow_html=True) - -styled_caption = """ -

-🚀 An Embedchain app powered with Unacademy\'s UPSC data! -

-""" -st.markdown(styled_caption, unsafe_allow_html=True) - -with st.expander(":grey[Want to create your own Unacademy UPSC AI?]"): - st.write( - """ - ```bash - pip install embedchain - ``` - - ```python - from embedchain import App - unacademy_ai_app = App() - unacademy_ai_app.add( - "https://unacademy.com/content/upsc/study-material/plan-policy/atma-nirbhar-bharat-3-0/", - data_type="web_page" - ) - unacademy_ai_app.chat("What is Atma Nirbhar 3.0?") - ``` - - For more information, checkout the [Embedchain docs](https://docs.embedchain.ai/get-started/quickstart). - """ - ) - -if "messages" not in st.session_state: - st.session_state.messages = [ - { - "role": "assistant", - "content": """Hi, I'm Unacademy UPSC AI bot, who can answer any questions related to UPSC preparation. - Let me help you prepare better for UPSC.\n -Sample questions: -- What are the subjects in UPSC CSE? -- What is the CSE scholarship price amount? -- What are different indian calendar forms? - """, - } - ] - -for message in st.session_state.messages: - role = message["role"] - with st.chat_message(role, avatar=assistant_avatar_url if role == "assistant" else None): - st.markdown(message["content"]) - -if prompt := st.chat_input("Ask me anything!"): - with st.chat_message("user"): - st.markdown(prompt) - st.session_state.messages.append({"role": "user", "content": prompt}) - - with st.chat_message("assistant", avatar=assistant_avatar_url): - msg_placeholder = st.empty() - msg_placeholder.markdown("Thinking...") - full_response = "" - - q = queue.Queue() - - def app_response(result): - llm_config = app.llm.config.as_dict() - llm_config["callbacks"] = [StreamingStdOutCallbackHandlerYield(q=q)] - config = BaseLlmConfig(**llm_config) - answer, citations = app.chat(prompt, config=config, citations=True) - result["answer"] = answer - result["citations"] = citations - - results = {} - - for answer_chunk in generate(q): - full_response += answer_chunk - msg_placeholder.markdown(full_response) - - answer, citations = results["answer"], results["citations"] - - if citations: - full_response += "\n\n**Sources**:\n" - sources = list(set(map(lambda x: x[1], citations))) - for i, source in enumerate(sources): - full_response += f"{i+1}. {source}\n" - - msg_placeholder.markdown(full_response) - st.session_state.messages.append({"role": "assistant", "content": full_response}) diff --git a/embedchain/examples/unacademy-ai/requirements.txt b/embedchain/examples/unacademy-ai/requirements.txt deleted file mode 100644 index bba32905a..000000000 --- a/embedchain/examples/unacademy-ai/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -embedchain -streamlit -pysqlite3-binary \ No newline at end of file diff --git a/embedchain/examples/whatsapp_bot/.env.example b/embedchain/examples/whatsapp_bot/.env.example deleted file mode 100644 index e570b8b55..000000000 --- a/embedchain/examples/whatsapp_bot/.env.example +++ /dev/null @@ -1 +0,0 @@ -OPENAI_API_KEY= diff --git a/embedchain/examples/whatsapp_bot/.gitignore b/embedchain/examples/whatsapp_bot/.gitignore deleted file mode 100644 index 2227fe3e2..000000000 --- a/embedchain/examples/whatsapp_bot/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -__pycache__ -db -database -pyenv -venv -.env -trash_files/ -.ideas.md \ No newline at end of file diff --git a/embedchain/examples/whatsapp_bot/Dockerfile b/embedchain/examples/whatsapp_bot/Dockerfile deleted file mode 100644 index 528f2eea6..000000000 --- a/embedchain/examples/whatsapp_bot/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM python:3.11-slim - -WORKDIR /usr/src/ -COPY requirements.txt . -RUN pip install -r requirements.txt - -COPY . . - -EXPOSE 8000 - -CMD ["python", "whatsapp_bot.py"] diff --git a/embedchain/examples/whatsapp_bot/README.md b/embedchain/examples/whatsapp_bot/README.md deleted file mode 100644 index 54cbf5c25..000000000 --- a/embedchain/examples/whatsapp_bot/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# WhatsApp Bot - -This is a replit template to create your own WhatsApp bot using the embedchain package. To know more about the bot and how to use it, go [here](https://docs.embedchain.ai/examples/whatsapp_bot). \ No newline at end of file diff --git a/embedchain/examples/whatsapp_bot/requirements.txt b/embedchain/examples/whatsapp_bot/requirements.txt deleted file mode 100644 index ea2517403..000000000 --- a/embedchain/examples/whatsapp_bot/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -Flask==2.3.2 -twilio==8.5.0 -embedchain \ No newline at end of file diff --git a/embedchain/examples/whatsapp_bot/run.py b/embedchain/examples/whatsapp_bot/run.py deleted file mode 100644 index 92e26be15..000000000 --- a/embedchain/examples/whatsapp_bot/run.py +++ /dev/null @@ -1,10 +0,0 @@ -from embedchain.bots.whatsapp import WhatsAppBot - - -def main(): - whatsapp_bot = WhatsAppBot() - whatsapp_bot.start() - - -if __name__ == "__main__": - main() diff --git a/embedchain/examples/whatsapp_bot/whatsapp_bot.py b/embedchain/examples/whatsapp_bot/whatsapp_bot.py deleted file mode 100644 index 50f9c16dd..000000000 --- a/embedchain/examples/whatsapp_bot/whatsapp_bot.py +++ /dev/null @@ -1,51 +0,0 @@ -from flask import Flask, request -from twilio.twiml.messaging_response import MessagingResponse - -from embedchain import App - -app = Flask(__name__) -chat_bot = App() - - -@app.route("/chat", methods=["POST"]) -def chat(): - incoming_message = request.values.get("Body", "").lower() - response = handle_message(incoming_message) - twilio_response = MessagingResponse() - twilio_response.message(response) - return str(twilio_response) - - -def handle_message(message): - if message.startswith("add "): - response = add_sources(message) - else: - response = query(message) - return response - - -def add_sources(message): - message_parts = message.split(" ", 2) - if len(message_parts) == 3: - data_type = message_parts[1] - url_or_text = message_parts[2] - try: - chat_bot.add(data_type, url_or_text) - response = f"Added {data_type}: {url_or_text}" - except Exception as e: - response = f"Failed to add {data_type}: {url_or_text}.\nError: {str(e)}" - else: - response = "Invalid 'add' command format.\nUse: add " - return response - - -def query(message): - try: - response = chat_bot.chat(message) - except Exception: - response = "An error occurred. Please try again!" - return response - - -if __name__ == "__main__": - app.run(host="0.0.0.0", port=8000, debug=False) diff --git a/embedchain/notebooks/anthropic.ipynb b/embedchain/notebooks/anthropic.ipynb deleted file mode 100644 index 2264d50fc..000000000 --- a/embedchain/notebooks/anthropic.ipynb +++ /dev/null @@ -1,161 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using Anthropic with Embedchain\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "-NbXjAdlh0vJ", - "outputId": "efdce0dc-fb30-4e01-f5a8-ef1a7f4e8c09" - }, - "outputs": [], - "source": [ - "!pip install embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set Anthropic related environment variables\n", - "\n", - "You can find `OPENAI_API_KEY` on your [OpenAI dashboard](https://platform.openai.com/account/api-keys) and `ANTHROPIC_API_KEY` on your [Anthropic dashboard](https://console.anthropic.com/account/keys)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"OPENAI_API_KEY\"] = \"sk-xxx\"\n", - "os.environ[\"ANTHROPIC_API_KEY\"] = \"xxx\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3: Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Amzxk3m-i3tD" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"provider\": \"anthropic\",\n", - " \"config\": {\n", - " \"model\": \"claude-instant-1\",\n", - " \"temperature\": 0.5,\n", - " \"top_p\": 1,\n", - " \"stream\": False\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 52 - }, - "id": "Sn_0rx9QjIY9", - "outputId": "dc17baec-39b5-4dc8-bd42-f2aad92697eb" - }, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 391 - }, - "id": "cvIK7dWRjN_f", - "outputId": "3d1cb7ce-969e-4dad-d48c-b818b7447cc0" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/notebooks/aws-bedrock.ipynb b/embedchain/notebooks/aws-bedrock.ipynb deleted file mode 100644 index 15995f706..000000000 --- a/embedchain/notebooks/aws-bedrock.ipynb +++ /dev/null @@ -1,226 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "63ab5e89", - "metadata": {}, - "source": [ - "## Cookbook for using Azure OpenAI with Embedchain" - ] - }, - { - "cell_type": "markdown", - "id": "e32a0265", - "metadata": {}, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b80ff15a", - "metadata": {}, - "outputs": [], - "source": [ - "!pip install embedchain" - ] - }, - { - "cell_type": "markdown", - "id": "ac982a56", - "metadata": {}, - "source": [ - "### Step-2: Set AWS related environment variables\n", - "\n", - "You can find these env variables on your AWS Management Console." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "e0a36133", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "\n", - "os.environ[\"AWS_ACCESS_KEY_ID\"] = \"AKIAIOSFODNN7EXAMPLE\" # replace with your AWS_ACCESS_KEY_ID\n", - "os.environ[\"AWS_SECRET_ACCESS_KEY\"] = \"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\" # replace with your AWS_SECRET_ACCESS_KEY\n", - "os.environ[\"AWS_SESSION_TOKEN\"] = \"IQoJb3JpZ2luX2VjEJr...==\" # replace with your AWS_SESSION_TOKEN\n", - "os.environ[\"AWS_DEFAULT_REGION\"] = \"us-east-1\" # replace with your AWS_DEFAULT_REGION\n", - "\n", - "from embedchain import App\n" - ] - }, - { - "cell_type": "markdown", - "id": "7d7b554e", - "metadata": {}, - "source": [ - "### Step-3: Define your llm and embedding model config\n", - "\n", - "May need to install langchain-anthropic to try with claude models" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "b9f52fc5", - "metadata": {}, - "outputs": [], - "source": [ - "config = \"\"\"\n", - "llm:\n", - " provider: aws_bedrock\n", - " config:\n", - " model: 'amazon.titan-text-express-v1'\n", - " deployment_name: ec_titan_express_v1\n", - " temperature: 0.5\n", - " max_tokens: 1000\n", - " top_p: 1\n", - " stream: false\n", - "\n", - "embedder:\n", - " provider: aws_bedrock\n", - " config:\n", - " model: amazon.titan-embed-text-v2:0\n", - " deployment_name: ec_embeddings_titan_v2\n", - "\"\"\"\n", - "\n", - "# Write the multi-line string to a YAML file\n", - "with open('aws_bedrock.yaml', 'w') as file:\n", - " file.write(config)" - ] - }, - { - "cell_type": "markdown", - "id": "98a11130", - "metadata": {}, - "source": [ - "### Step-4 Create two embedchain apps based on the config" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "1ee9bdd9", - "metadata": {}, - "outputs": [], - "source": [ - "app = App.from_config(config_path=\"aws_bedrock.yaml\")\n", - "app.reset() # Reset the app to clear the cache and start fresh" - ] - }, - { - "cell_type": "markdown", - "id": "554dc97b", - "metadata": {}, - "source": [ - "### Step-5: Add a data source to unrelated to the question you are asking" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "686ae765", - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Inserting batches in chromadb: 100%|██████████| 1/1 [00:01<00:00, 1.62s/it]\n" - ] - }, - { - "data": { - "text/plain": [ - "'81b4936ef6f24974235a56acc1913c46'" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "app.add(\"https://www.lipsum.com/\")" - ] - }, - { - "cell_type": "markdown", - "id": "ccc7d421", - "metadata": {}, - "source": [ - "### Step-6: Notice the underlying context changing with the updated data source" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "27868a7d", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Context: 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of \"de Finibus Bonorum et Malorum\" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, \"Lorem ipsum dolor sit amet.\", comes from a line in section 1.10.32.The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from \"de Finibus Bonorum et Malorum\" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham. Where can I get some? There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc. Donate: If you use this site regularly and would like to help keep the site on the Internet, please consider donating a small sum to help pay for the hosting and bandwidth bill. There is no minimum donation, any sum is appreciated - click here to donate using PayPal. Thank you for your support. Donate bitcoin: Lorem Ipsum - All the facts - Lipsum generator Հայերեն Shqip ‫العربية Български Català 中文简体 Hrvatski Česky Dansk Nederlands English Eesti Filipino Suomi Français ქართული Deutsch Ελληνικά ‫עברית हिन्दी Magyar Indonesia Italiano Latviski Lietuviškai македонски Melayu Norsk Polski Português Româna Pyccкий Српски Slovenčina Slovenščina Español Svenska ไทย Türkçe Українська Tiếng Việt Lorem Ipsum \"Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.\" \"There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain.\" What is Lorem Ipsum? Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. Why do we use it? It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like). Where does it come from? Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 16UQLq1HZ3CNwhvgrarV6pMoA2CDjb4tyF Translations: Can you help translate this site into a foreign language ? Please email us with details if you can help. There is a set of mock banners available here in three colours and in a range of standard banner sizes: NodeJS Python Interface GTK Lipsum Rails .NET The standard Lorem Ipsum passage, used since the 1500s\"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\"Section 1.10.32 of \"de Finibus Bonorum et Malorum\", written by Cicero in 45 BC\"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?\" 1914 translation by H. Rackham \"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Inserting batches in chromadb: 100%|██████████| 1/1 [00:01<00:00, 1.26s/it]\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Context with updated memory: Elon Musk PROFILEElon MuskCEO, Tesla$234.1B$6.6B (2.73%)Real Time Net Worthas of 8/1/24Reflects change since 5 pm ET of prior trading day. 1 in the world todayPhoto by Martin Schoeller for ForbesAbout Elon MuskElon Musk cofounded six companies, including electric car maker Tesla, rocket producer SpaceX and tunneling startup Boring Company.He owns about 12% of Tesla excluding options, but has pledged more than half his shares as collateral for personal loans of up to $3.5 billion.In early 2024, a Delaware judge voided Musk's 2018 deal to receive options equaling an additional 9% of Tesla. Forbes has discounted the options by 50% pending Musk's appeal.SpaceX, founded in 2002, is worth nearly $180 billion after a December 2023 tender offer of up to $750 million; SpaceX stock has quintupled its value in four years.Musk bought Twitter in 2022 for $44 billion, after later trying to back out of the deal. He owns an estimated 74% of the company, now called X.Forbes estimates that Musk's stake in X is now worth nearly 70% less than he paid for it based on investor Fidelity's valuation of the company as of December 2023.Wealth HistoryHOVER TO REVEAL NET WORTH BY YEARForbes ListsThe Richest Person In Every State (2024) 2Billionaires (2024) 1Forbes 400 (2023) 1Innovative Leaders (2019) 25Powerful People (2018) 12Richest In Tech (2017)Global Game Changers (2016)More ListsPersonal StatsAge53Source of WealthTesla, SpaceX, Self MadeSelf-Made Score8Philanthropy Score1ResidenceAustin, TexasCitizenshipUnited StatesMarital StatusSingleChildren11EducationBachelor of Arts/Science, University of PennsylvaniaDid you knowMusk, who says he's worried about population collapse, has ten children with three women, including triplets and two sets of twins.As a kid in South Africa, Musk taught himself to code; he sold his first game, Blastar, for about $500.In Their Own WordsI operate on the physics approach to analysis. You boil things down to the first principles or fundamental truths in a particular area and then you reason up from there.Elon MuskRelated People & CompaniesReid HoffmanView ProfileTeslaHolds stake in TeslaView ProfileUniversity of PennsylvaniaAttended the schoolView ProfilePeter ThielCofounderView ProfileRobyn DenholmRelated by employment: TeslaView ProfileLarry EllisonRelated by financial asset: TeslaView ProfileSee MoreSee LessMore on Forbes2 hours agoDon Lemon Sues Elon Musk After $1.5 Million-Per-Year X Deal Fell ApartDon Lemon sues Elon Musk for refusing to pay him after an exclusive deal with the reporter on X fell apart.ByKirk OgunrindeContributor17 hours agoElon Musk’s Experimental School In Texas Is Now Looking For StudentsCalled Ad Astra, Musk has said the school will focus on “making all the children go through the same grade at the same time, like an assembly line.”BySarah EmersonForbes StaffJul 31, 2024Elon Musk Isn't Stopping Misinformation, He's Helped Spread ItThough hardly the most egregious example of a manipulated video, it is the fact that X failed to flag it that has raised concerns.ByPeter SuciuContributorJul 30, 2024Elon Musk Suddenly Breaks His Silence On Bitcoin After Issuing A Shock U.S. Dollar ‘Destruction’ Warning That Could Trigger A Crypto Price BoomElon Musk, the billionaire chief executive of Tesla, has mostly steered clear of bitcoin and crypto comments following the bitcoin price crash in 2022.ByBilly BambroughSenior ContributorJul 30, 20245 Reasons Deep Fakes (And Elon Musk) Won’t Destroy DemocracyWe've been dealing with things like deep fakes and people like Musk since the dawn of time. Five basic 'shadow skills' are why democracy is not in danger.ByPia LauritzenContributorJul 27, 2024Grimes’ Mother Blasts Musk—Accuses Him Of Keeping Children From Their MotherThe mother of billionaire Elon Musk’s former partner, musician Grimes, claimed Musk is withholding his children from their mother.ByBrian BushardForbes StaffJul 24, 2024Elon Musk Attends Netanyahu’s Speech To Congress As His GuestNetanyahu is speaking to Congress about Israel’s war with Hamas.ByAntonio Pequeño IVForbes StaffJul 24, 2024Elon Musk’s Net Worth Falls $16 Billion As Tesla Stock TanksMusk remains the richest person on Earth even after losing the equivalent of the 113th-wealthiest person’s entire fortune in one morning. ByDerek SaulForbes StaffJul 24, 2024Elon Musk’s Endorsement Of Trump Could Be A Grave Mistake For TeslaThe billionaire's embrace of the anti-EV presidential candidate risks politicizing a brand that sells best in California and, based on market studies, with Democrats.ByAlan OhnsmanForbes StaffJul 23, 2024The Prompt: Elon Musk’s ‘Gigafactory Of Compute’ Is Running In MemphisPlus: Target’s AI chatbot for employees misses the mark. ByRashi ShrivastavaForbes StaffJul 22, 2024‘Fortnite’ Is Getting Elon Musk’s Tesla Cybertruck As A New Combat VehicleAccording to a new trailer just released today, Elon Musk’s beloved Tesla Cybertruck is being released in Fortnite ByPaul TassiSenior ContributorJul 22, 2024Elon Musk’s Mad Dash To Build A Power-Hungry AI SupercomputerIn this week's Current Climate newsletter, Elon Musk's mad dash to build a water- and power-hungry AI supercomputer, Vietnamese billionaire's VinFast delays U.S. factory, and biomass-based carbon removalByAmy FeldmanForbes StaffJul 19, 2024There Are 10,000 Active Satellites In Orbit. Most Belong To Elon MuskIt’s a milestone that showcases decades of technical achievement, but might also make it harder to sleep at night if you think about it for too long. ByEric MackSenior ContributorJul 17, 2024Inside Elon Musk’s Mad Dash To Build A Giant xAI Supercomputer In MemphisElon Musk is “hauling ass” on his supercomputer project in Memphis. But a whiplash deal, NDAs and backroom promises made to the city have lawmakers demanding answers.BySarah EmersonForbes StaffJul 16, 2024Elon Musk To Move X And SpaceX Headquarters To TexasUpset with a new California law protecting the rights of transgender children, Elon Musk is moving his two\n" - ] - } - ], - "source": [ - "question = \"Who is Elon Musk?\"\n", - "context = \" \".join([a['context'] for a in app.search(question)])\n", - "print(\"Context:\", context)\n", - "app.add(\"https://www.forbes.com/profile/elon-musk\")\n", - "context = \" \".join([a['context'] for a in app.search(question)])\n", - "print(\"Context with updated memory:\", context)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2c607570", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/embedchain/notebooks/azure-openai.ipynb b/embedchain/notebooks/azure-openai.ipynb deleted file mode 100644 index 6d9d1a936..000000000 --- a/embedchain/notebooks/azure-openai.ipynb +++ /dev/null @@ -1,174 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "63ab5e89", - "metadata": {}, - "source": [ - "## Cookbook for using Azure OpenAI with Embedchain" - ] - }, - { - "cell_type": "markdown", - "id": "e32a0265", - "metadata": {}, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b80ff15a", - "metadata": {}, - "outputs": [], - "source": [ - "!pip install embedchain" - ] - }, - { - "cell_type": "markdown", - "id": "ac982a56", - "metadata": {}, - "source": [ - "### Step-2: Set Azure OpenAI related environment variables\n", - "\n", - "You can find these env variables on your Azure OpenAI dashboard." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e0a36133", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"OPENAI_API_TYPE\"] = \"azure\"\n", - "os.environ[\"OPENAI_API_BASE\"] = \"https://xxx.openai.azure.com/\"\n", - "os.environ[\"OPENAI_API_KEY\"] = \"xxx\"\n", - "os.environ[\"OPENAI_API_VERSION\"] = \"xxx\"" - ] - }, - { - "cell_type": "markdown", - "id": "7d7b554e", - "metadata": {}, - "source": [ - "### Step-3: Define your llm and embedding model config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b9f52fc5", - "metadata": {}, - "outputs": [], - "source": [ - "config = \"\"\"\n", - "llm:\n", - " provider: azure_openai\n", - " model: gpt-35-turbo\n", - " config:\n", - " deployment_name: ec_openai_azure\n", - " temperature: 0.5\n", - " max_tokens: 1000\n", - " top_p: 1\n", - " stream: false\n", - "\n", - "embedder:\n", - " provider: azure_openai\n", - " config:\n", - " model: text-embedding-ada-002\n", - " deployment_name: ec_embeddings_ada_002\n", - "\"\"\"\n", - "\n", - "# Write the multi-line string to a YAML file\n", - "with open('azure_openai.yaml', 'w') as file:\n", - " file.write(config)" - ] - }, - { - "cell_type": "markdown", - "id": "98a11130", - "metadata": {}, - "source": [ - "### Step-4 Create embedchain app based on the config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1ee9bdd9", - "metadata": {}, - "outputs": [], - "source": [ - "app = App.from_config(config_path=\"azure_openai.yaml\")" - ] - }, - { - "cell_type": "markdown", - "id": "554dc97b", - "metadata": {}, - "source": [ - "### Step-5: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "686ae765", - "metadata": {}, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "id": "ccc7d421", - "metadata": {}, - "source": [ - "### Step-6: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "27868a7d", - "metadata": {}, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/embedchain/notebooks/azure_openai.yaml b/embedchain/notebooks/azure_openai.yaml deleted file mode 100644 index 15a069032..000000000 --- a/embedchain/notebooks/azure_openai.yaml +++ /dev/null @@ -1,16 +0,0 @@ - -llm: - provider: azure_openai - model: gpt-35-turbo - config: - deployment_name: ec_openai_azure - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -embedder: - provider: azure_openai - config: - model: text-embedding-ada-002 - deployment_name: ec_embeddings_ada_002 diff --git a/embedchain/notebooks/chromadb.ipynb b/embedchain/notebooks/chromadb.ipynb deleted file mode 100644 index d74851efd..000000000 --- a/embedchain/notebooks/chromadb.ipynb +++ /dev/null @@ -1,147 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using ChromaDB with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "-NbXjAdlh0vJ" - }, - "outputs": [], - "source": [ - "!pip install embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set OpenAI environment variables\n", - "\n", - "You can find this env variable on your [OpenAI dashboard](https://platform.openai.com/account/api-keys)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"OPENAI_API_KEY\"] = \"sk-xxx\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3 Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Amzxk3m-i3tD" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"vectordb\": {\n", - " \"provider\": \"chroma\",\n", - " \"config\": {\n", - " \"collection_name\": \"my-collection\",\n", - " \"host\": \"your-chromadb-url.com\",\n", - " \"port\": 5200,\n", - " \"allow_reset\": True\n", - " }\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Sn_0rx9QjIY9" - }, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "cvIK7dWRjN_f" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/notebooks/clarifai.ipynb b/embedchain/notebooks/clarifai.ipynb deleted file mode 100644 index e01400603..000000000 --- a/embedchain/notebooks/clarifai.ipynb +++ /dev/null @@ -1,135 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Cookbook for using Clarifai LLM and Embedders with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Step-1: Install embedchain-clarifai package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "!pip install embedchain[clarifai]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Step-2: Set Clarifai PAT as env variable.\n", - "Sign-up to [Clarifai](https://clarifai.com/signup?utm_source=clarifai_home&utm_medium=direct&) platform and you can obtain `CLARIFAI_PAT` by following this [link](https://docs.clarifai.com/clarifai-basics/authentication/personal-access-tokens/).\n", - "\n", - "optionally you can also pass `api_key` in config of llm/embedder class." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"CLARIFAI_PAT\"]=\"xxx\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Step-3 Create embedchain app using clarifai LLM and embedder and define your config.\n", - "\n", - "Browse through Clarifai community page to get the URL of different [LLM](https://clarifai.com/explore/models?page=1&perPage=24&filterData=%5B%7B%22field%22%3A%22use_cases%22%2C%22value%22%3A%5B%22llm%22%5D%7D%5D) and [embedding](https://clarifai.com/explore/models?page=1&perPage=24&filterData=%5B%7B%22field%22%3A%22input_fields%22%2C%22value%22%3A%5B%22text%22%5D%7D%2C%7B%22field%22%3A%22output_fields%22%2C%22value%22%3A%5B%22embeddings%22%5D%7D%5D) models available." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Use model_kwargs to pass all model specific parameters for inference.\n", - "app = App.from_config(config={\n", - " \"llm\": {\n", - " \"provider\": \"clarifai\",\n", - " \"config\": {\n", - " \"model\": \"https://clarifai.com/mistralai/completion/models/mistral-7B-Instruct\",\n", - " \"model_kwargs\": {\n", - " \"temperature\": 0.5,\n", - " \"max_tokens\": 1000\n", - " }\n", - " }\n", - " },\n", - " \"embedder\": {\n", - " \"provider\": \"clarifai\",\n", - " \"config\": {\n", - " \"model\": \"https://clarifai.com/openai/embed/models/text-embedding-ada\",\n", - " }\n", - "}\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "v1", - "language": "python", - "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.9.10" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/embedchain/notebooks/cohere.ipynb b/embedchain/notebooks/cohere.ipynb deleted file mode 100644 index 26df9c83f..000000000 --- a/embedchain/notebooks/cohere.ipynb +++ /dev/null @@ -1,165 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using Cohere with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "-NbXjAdlh0vJ", - "outputId": "fae77912-4e6a-4c78-fcb7-fbbe46f7a9c7" - }, - "outputs": [], - "source": [ - "!pip install embedchain[cohere]" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set Cohere related environment variables\n", - "\n", - "You can find `OPENAI_API_KEY` on your [OpenAI dashboard](https://platform.openai.com/account/api-keys) and `COHERE_API_KEY` key on your [Cohere dashboard](https://dashboard.cohere.com/api-keys)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"OPENAI_API_KEY\"] = \"sk-xxx\"\n", - "os.environ[\"COHERE_API_KEY\"] = \"xxx\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3 Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 321 - }, - "id": "Amzxk3m-i3tD", - "outputId": "afe8afde-5cb8-46bc-c541-3ad26cc3fa6e" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"provider\": \"cohere\",\n", - " \"config\": {\n", - " \"model\": \"gptd-instruct-tft\",\n", - " \"temperature\": 0.5,\n", - " \"max_tokens\": 1000,\n", - " \"top_p\": 1,\n", - " \"stream\": False\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 176 - }, - "id": "Sn_0rx9QjIY9", - "outputId": "2f2718a4-3b7e-4844-fd46-3e0857653ca0" - }, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "cvIK7dWRjN_f", - "outputId": "79e873c8-9594-45da-f5a3-0a893511267f" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/notebooks/elasticsearch.ipynb b/embedchain/notebooks/elasticsearch.ipynb deleted file mode 100644 index c507efd2b..000000000 --- a/embedchain/notebooks/elasticsearch.ipynb +++ /dev/null @@ -1,145 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using ElasticSearchDB with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "-NbXjAdlh0vJ" - }, - "outputs": [], - "source": [ - "!pip install embedchain[elasticsearch]" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set OpenAI environment variables.\n", - "\n", - "You can find this env variable on your [OpenAI dashboard](https://platform.openai.com/account/api-keys)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"OPENAI_API_KEY\"] = \"sk-xxx\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3 Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Amzxk3m-i3tD" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"provider\": \"elasticsearch\",\n", - " \"config\": {\n", - " \"collection_name\": \"es-index\",\n", - " \"es_url\": \"your-elasticsearch-url.com\",\n", - " \"allow_reset\": True,\n", - " \"api_key\": \"xxx\"\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Sn_0rx9QjIY9" - }, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "cvIK7dWRjN_f" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/notebooks/embedchain-chromadb-server.ipynb b/embedchain/notebooks/embedchain-chromadb-server.ipynb deleted file mode 100644 index 254c0bbce..000000000 --- a/embedchain/notebooks/embedchain-chromadb-server.ipynb +++ /dev/null @@ -1,111 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "553f2e71", - "metadata": {}, - "source": [ - "## Embedchain chromadb server example" - ] - }, - { - "cell_type": "markdown", - "id": "513e12e6", - "metadata": {}, - "source": [ - "This notebook shows an example of how you can use embedchain with chromdb (server). \n", - "\n", - "\n", - "First, run chroma inside docker using the following command:\n", - "\n", - "\n", - "```bash\n", - "git clone https://github.com/chroma-core/chroma\n", - "cd chroma && docker-compose up -d --build\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "92e7ad71", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "from embedchain.config import AppConfig\n", - "\n", - "\n", - "chromadb_host = \"localhost\"\n", - "chromadb_port = 8000\n", - "\n", - "config = AppConfig(host=chromadb_host, port=chromadb_port)\n", - "elon_bot = App(config)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "1a6d6841", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "All data from https://en.wikipedia.org/wiki/Elon_Musk already exists in the database.\n", - "All data from https://www.tesla.com/elon-musk already exists in the database.\n" - ] - } - ], - "source": [ - "# Embed Online Resources\n", - "elon_bot.add(\"web_page\", \"https://en.wikipedia.org/wiki/Elon_Musk\")\n", - "elon_bot.add(\"web_page\", \"https://www.tesla.com/elon-musk\")" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "34cda99c", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Elon Musk runs four companies: Tesla, SpaceX, Neuralink, and The Boring Company.'" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "elon_bot.query(\"How many companies does Elon Musk run?\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/embedchain/notebooks/embedchain-docs-site-example.ipynb b/embedchain/notebooks/embedchain-docs-site-example.ipynb deleted file mode 100644 index 27f28f322..000000000 --- a/embedchain/notebooks/embedchain-docs-site-example.ipynb +++ /dev/null @@ -1,121 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "e9a9dc6a", - "metadata": {}, - "outputs": [], - "source": [ - "from embedchain import App\n", - "\n", - "embedchain_docs_bot = App()" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "c1c24d68", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "All data from https://docs.embedchain.ai/ already exists in the database.\n" - ] - } - ], - "source": [ - "embedchain_docs_bot.add(\"docs_site\", \"https://docs.embedchain.ai/\")" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "48cdaecf", - "metadata": {}, - "outputs": [], - "source": [ - "answer = embedchain_docs_bot.query(\"Write a flask API for embedchain bot\")" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "0fe18085", - "metadata": {}, - "outputs": [ - { - "data": { - "text/markdown": [ - "To write a Flask API for the embedchain bot, you can use the following code snippet:\n", - "\n", - "```python\n", - "from flask import Flask, request, jsonify\n", - "from embedchain import App\n", - "\n", - "app = Flask(__name__)\n", - "bot = App()\n", - "\n", - "# Add datasets to the bot\n", - "bot.add(\"youtube_video\", \"https://www.youtube.com/watch?v=3qHkcs3kG44\")\n", - "bot.add(\"pdf_file\", \"https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf\")\n", - "\n", - "@app.route('/query', methods=['POST'])\n", - "def query():\n", - " data = request.get_json()\n", - " question = data['question']\n", - " response = bot.query(question)\n", - " return jsonify({'response': response})\n", - "\n", - "if __name__ == '__main__':\n", - " app.run()\n", - "```\n", - "\n", - "In this code, we create a Flask app and initialize an instance of the embedchain bot. We then add the desired datasets to the bot using the `add()` function.\n", - "\n", - "Next, we define a route `/query` that accepts POST requests. The request body should contain a JSON object with a `question` field. The bot's `query()` function is called with the provided question, and the response is returned as a JSON object.\n", - "\n", - "Finally, we run the Flask app using `app.run()`.\n", - "\n", - "Note: Make sure to install Flask and embedchain packages before running this code." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import Markdown\n", - "# Create a Markdown object and display it\n", - "markdown_answer = Markdown(answer)\n", - "display(markdown_answer)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/embedchain/notebooks/gpt4all.ipynb b/embedchain/notebooks/gpt4all.ipynb deleted file mode 100644 index 1bad7ebd3..000000000 --- a/embedchain/notebooks/gpt4all.ipynb +++ /dev/null @@ -1,169 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using GPT4All with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "-NbXjAdlh0vJ", - "outputId": "077fa470-b51f-4c29-8c22-9c5f0a9cef47" - }, - "outputs": [], - "source": [ - "!pip install embedchain[opensource]" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set GPT4ALL related environment variables\n", - "\n", - "GPT4All is free for all and doesn't require any API Key to use it. So you can use it for free!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "from embedchain import App" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3 Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "Amzxk3m-i3tD", - "outputId": "775db99b-e217-47db-f87f-788495d86f26" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"llm\": {\n", - " \"provider\": \"gpt4all\",\n", - " \"config\": {\n", - " \"model\": \"orca-mini-3b-gguf2-q4_0.gguf\",\n", - " \"temperature\": 0.5,\n", - " \"max_tokens\": 1000,\n", - " \"top_p\": 1,\n", - " \"stream\": False\n", - " }\n", - " },\n", - " \"embedder\": {\n", - " \"provider\": \"gpt4all\",\n", - " \"config\": {\n", - " \"model\": \"all-MiniLM-L6-v2\"\n", - " }\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 52 - }, - "id": "Sn_0rx9QjIY9", - "outputId": "c6514f17-3cb2-4fbc-c80d-79b3a311ff30" - }, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 480 - }, - "id": "cvIK7dWRjN_f", - "outputId": "c74f356a-d2fb-426d-b36c-d84911397338" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/notebooks/hugging_face_hub.ipynb b/embedchain/notebooks/hugging_face_hub.ipynb deleted file mode 100644 index eff2dc932..000000000 --- a/embedchain/notebooks/hugging_face_hub.ipynb +++ /dev/null @@ -1,168 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using Hugging Face Hub with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 1000 - }, - "id": "-NbXjAdlh0vJ", - "outputId": "35ddc904-8067-44cf-dcc9-3c8b4cd29989" - }, - "outputs": [], - "source": [ - "!pip install embedchain[huggingface_hub,opensource]" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set Hugging Face Hub related environment variables\n", - "\n", - "You can find your `HUGGINGFACE_ACCESS_TOKEN` key on your [Hugging Face Hub dashboard](https://huggingface.co/settings/tokens)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"HUGGINGFACE_ACCESS_TOKEN\"] = \"hf_xxx\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3 Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Amzxk3m-i3tD" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"llm\": {\n", - " \"provider\": \"huggingface\",\n", - " \"config\": {\n", - " \"model\": \"google/flan-t5-xxl\",\n", - " \"temperature\": 0.5,\n", - " \"max_tokens\": 1000,\n", - " \"top_p\": 0.8,\n", - " \"stream\": False\n", - " }\n", - " },\n", - " \"embedder\": {\n", - " \"provider\": \"huggingface\",\n", - " \"config\": {\n", - " \"model\": \"sentence-transformers/all-mpnet-base-v2\"\n", - " }\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 70 - }, - "id": "Sn_0rx9QjIY9", - "outputId": "3c2a803a-3a93-4b0d-a6ae-17ae3c96c3c2" - }, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "cvIK7dWRjN_f", - "outputId": "47a89d1c-b322-495c-822a-6c2ecef894d2" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/notebooks/jina.ipynb b/embedchain/notebooks/jina.ipynb deleted file mode 100644 index b89a2aa22..000000000 --- a/embedchain/notebooks/jina.ipynb +++ /dev/null @@ -1,165 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using JinaChat with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 1000 - }, - "id": "-NbXjAdlh0vJ", - "outputId": "69cb79a6-c758-4656-ccf7-9f3105c81d16" - }, - "outputs": [], - "source": [ - "!pip install embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set JinaChat related environment variables\n", - "\n", - "You can find `OPENAI_API_KEY` on your [OpenAI dashboard](https://platform.openai.com/account/api-keys) and `JINACHAT_API_KEY` key on your [Chat Jina dashboard](https://chat.jina.ai/api)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"OPENAI_API_KEY\"] = \"sk-xxx\"\n", - "os.environ[\"JINACHAT_API_KEY\"] = \"xxx\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3 Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 321 - }, - "id": "Amzxk3m-i3tD", - "outputId": "8d00da74-5f73-49bb-b868-dcf1c375ac85" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"provider\": \"jina\",\n", - " \"config\": {\n", - " \"temperature\": 0.5,\n", - " \"max_tokens\": 1000,\n", - " \"top_p\": 1,\n", - " \"stream\": False\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 52 - }, - "id": "Sn_0rx9QjIY9", - "outputId": "10eeacc7-9263-448e-876d-002af897ebe5" - }, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "cvIK7dWRjN_f", - "outputId": "7dc7212f-a0e9-43c8-f119-f595ba79b4b7" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/notebooks/lancedb.ipynb b/embedchain/notebooks/lancedb.ipynb deleted file mode 100644 index 08d99621a..000000000 --- a/embedchain/notebooks/lancedb.ipynb +++ /dev/null @@ -1,146 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using LanceDB with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "-NbXjAdlh0vJ" - }, - "outputs": [], - "source": [ - "! pip install embedchain lancedb" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set environment variables needed for LanceDB\n", - "\n", - "You can find this env variable on your [OpenAI](https://platform.openai.com/account/api-keys)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"OPENAI_API_KEY\"] = \"sk-xxx\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3 Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Amzxk3m-i3tD" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"vectordb\": {\n", - " \"provider\": \"lancedb\",\n", - " \"config\": {\n", - " \"collection_name\": \"lancedb-index\"\n", - " }\n", - " }\n", - " }\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Sn_0rx9QjIY9" - }, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "cvIK7dWRjN_f" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/notebooks/llama2.ipynb b/embedchain/notebooks/llama2.ipynb deleted file mode 100644 index eabf7490b..000000000 --- a/embedchain/notebooks/llama2.ipynb +++ /dev/null @@ -1,161 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using LLAMA2 with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "-NbXjAdlh0vJ", - "outputId": "86a4a9b2-4ed6-431c-da6f-c3eacb390f42" - }, - "outputs": [], - "source": [ - "!pip install embedchain[llama2]" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set LLAMA2 related environment variables\n", - "\n", - "You can find `OPENAI_API_KEY` on your [OpenAI dashboard](https://platform.openai.com/account/api-keys) and `REPLICATE_API_TOKEN` key on your [Replicate dashboard](https://replicate.com/account/api-tokens)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"OPENAI_API_KEY\"] = \"sk-xxx\"\n", - "os.environ[\"REPLICATE_API_TOKEN\"] = \"xxx\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3 Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Amzxk3m-i3tD" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"provider\": \"llama2\",\n", - " \"config\": {\n", - " \"model\": \"a16z-infra/llama13b-v2-chat:df7690f1994d94e96ad9d568eac121aecf50684a0b0963b25a41cc40061269e5\",\n", - " \"temperature\": 0.5,\n", - " \"max_tokens\": 1000,\n", - " \"top_p\": 0.5,\n", - " \"stream\": False\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 52 - }, - "id": "Sn_0rx9QjIY9", - "outputId": "ba158e9c-0f16-4c6b-a876-7543120985a2" - }, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 599 - }, - "id": "cvIK7dWRjN_f", - "outputId": "e2d11a25-a2ed-4034-ec6a-e8a5986c89ae" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/notebooks/ollama.ipynb b/embedchain/notebooks/ollama.ipynb deleted file mode 100644 index 550c23628..000000000 --- a/embedchain/notebooks/ollama.ipynb +++ /dev/null @@ -1,207 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using Ollama with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Setup Ollama, follow these instructions https://github.com/jmorganca/ollama\n", - "\n", - "Once Setup is done:\n", - "\n", - "- ollama pull llama2 (All supported models can be found here: https://ollama.ai/library)\n", - "- ollama run llama2 (Test out the model once)\n", - "- ollama serve" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-2 Create embedchain app and define your config (all local inference)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 321 - }, - "id": "Amzxk3m-i3tD", - "outputId": "afe8afde-5cb8-46bc-c541-3ad26cc3fa6e" - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/sukkritsharma/workspace/embedchain/.venv/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n" - ] - } - ], - "source": [ - "from embedchain import App\n", - "app = App.from_config(config={\n", - " \"llm\": {\n", - " \"provider\": \"ollama\",\n", - " \"config\": {\n", - " \"model\": \"llama2\",\n", - " \"temperature\": 0.5,\n", - " \"top_p\": 1,\n", - " \"stream\": True\n", - " }\n", - " },\n", - " \"embedder\": {\n", - " \"provider\": \"huggingface\",\n", - " \"config\": {\n", - " \"model\": \"BAAI/bge-small-en-v1.5\"\n", - " }\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-3: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 176 - }, - "id": "Sn_0rx9QjIY9", - "outputId": "2f2718a4-3b7e-4844-fd46-3e0857653ca0" - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Inserting batches in chromadb: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 1.57it/s]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Successfully saved https://www.forbes.com/profile/elon-musk (DataType.WEB_PAGE). New chunks count: 4\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "text/plain": [ - "'8cf46026cabf9b05394a2658bd1fe890'" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-4: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "cvIK7dWRjN_f", - "outputId": "79e873c8-9594-45da-f5a3-0a893511267f" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Elon Musk is a business magnate, investor, and engineer. He is the CEO of SpaceX and Tesla, Inc., and has been involved in other successful ventures such as Neuralink and The Boring Company. Musk is known for his innovative ideas, entrepreneurial spirit, and vision for the future of humanity.\n", - "\n", - "As the CEO of Tesla, Musk has played a significant role in popularizing electric vehicles and making them more accessible to the masses. Under his leadership, Tesla has grown into one of the most valuable companies in the world.\n", - "\n", - "SpaceX, another company founded by Musk, is a leading player in the commercial space industry. SpaceX has developed advanced rockets and spacecraft, including the Falcon 9 and Dragon, which have successfully launched numerous satellites and other payloads into orbit.\n", - "\n", - "Musk is also known for his ambitious goals, such as establishing a human settlement on Mars and developing sustainable energy solutions to address climate change. He has been recognized for his philanthropic efforts, particularly in the area of education, and has been awarded numerous honors and awards for his contributions to society.\n", - "\n", - "Overall, Elon Musk is a highly influential and innovative entrepreneur who has made significant impacts in various industries and has inspired many people around the world with his vision and leadership." - ] - } - ], - "source": [ - "answer = app.query(\"who is elon musk?\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.9" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/embedchain/notebooks/openai.ipynb b/embedchain/notebooks/openai.ipynb deleted file mode 100644 index 39da4bb37..000000000 --- a/embedchain/notebooks/openai.ipynb +++ /dev/null @@ -1,160 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using OpenAI with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 1000 - }, - "id": "-NbXjAdlh0vJ", - "outputId": "6c630676-c7fc-4054-dc94-c613de58a037" - }, - "outputs": [], - "source": [ - "!pip install embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set OpenAI environment variables\n", - "\n", - "You can find this env variable on your [OpenAI dashboard](https://platform.openai.com/account/api-keys)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"OPENAI_API_KEY\"] = \"sk-xxx\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3 Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Amzxk3m-i3tD" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"llm\": {\n", - " \"provider\": \"openai\",\n", - " \"config\": {\n", - " \"model\": \"gpt-4o-mini\",\n", - " \"temperature\": 0.5,\n", - " \"max_tokens\": 1000,\n", - " \"top_p\": 1,\n", - " \"stream\": False\n", - " }\n", - " },\n", - " \"embedder\": {\n", - " \"provider\": \"openai\",\n", - " \"config\": {\n", - " \"model\": \"text-embedding-ada-002\"\n", - " }\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Sn_0rx9QjIY9" - }, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "cvIK7dWRjN_f" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.11.6" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/notebooks/openai_azure.yaml b/embedchain/notebooks/openai_azure.yaml deleted file mode 100644 index 15a069032..000000000 --- a/embedchain/notebooks/openai_azure.yaml +++ /dev/null @@ -1,16 +0,0 @@ - -llm: - provider: azure_openai - model: gpt-35-turbo - config: - deployment_name: ec_openai_azure - temperature: 0.5 - max_tokens: 1000 - top_p: 1 - stream: false - -embedder: - provider: azure_openai - config: - model: text-embedding-ada-002 - deployment_name: ec_embeddings_ada_002 diff --git a/embedchain/notebooks/opensearch.ipynb b/embedchain/notebooks/opensearch.ipynb deleted file mode 100644 index f9e678db5..000000000 --- a/embedchain/notebooks/opensearch.ipynb +++ /dev/null @@ -1,147 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using OpenSearchDB with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "-NbXjAdlh0vJ" - }, - "outputs": [], - "source": [ - "!pip install embedchain[opensearch]" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set OpenAI environment variables and install the dependencies.\n", - "\n", - "You can find this env variable on your [OpenAI dashboard](https://platform.openai.com/account/api-keys). Now lets install the dependencies needed for Opensearch." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"OPENAI_API_KEY\"] = \"sk-xxx\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3 Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Amzxk3m-i3tD" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"provider\": \"opensearch\",\n", - " \"config\": {\n", - " \"opensearch_url\": \"your-opensearch-url.com\",\n", - " \"http_auth\": [\"admin\", \"admin\"],\n", - " \"vector_dimension\": 1536,\n", - " \"collection_name\": \"my-app\",\n", - " \"use_ssl\": False,\n", - " \"verify_certs\": False\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Sn_0rx9QjIY9" - }, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "cvIK7dWRjN_f" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/notebooks/pinecone.ipynb b/embedchain/notebooks/pinecone.ipynb deleted file mode 100644 index 9dee9b209..000000000 --- a/embedchain/notebooks/pinecone.ipynb +++ /dev/null @@ -1,146 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using PineconeDB with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "-NbXjAdlh0vJ" - }, - "outputs": [], - "source": [ - "!pip install embedchain pinecone-client pinecone-text" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set environment variables needed for Pinecone\n", - "\n", - "You can find this env variable on your [OpenAI dashboard](https://platform.openai.com/account/api-keys) and [Pinecone dashboard](https://app.pinecone.io/)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"OPENAI_API_KEY\"] = \"sk-xxx\"\n", - "os.environ[\"PINECONE_API_KEY\"] = \"xxx\"\n", - "os.environ[\"PINECONE_ENV\"] = \"xxx\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3 Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Amzxk3m-i3tD" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"provider\": \"pinecone\",\n", - " \"config\": {\n", - " \"metric\": \"cosine\",\n", - " \"vector_dimension\": 768,\n", - " \"collection_name\": \"pc-index\"\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Sn_0rx9QjIY9" - }, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "cvIK7dWRjN_f" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/notebooks/together.ipynb b/embedchain/notebooks/together.ipynb deleted file mode 100644 index c2645cde8..000000000 --- a/embedchain/notebooks/together.ipynb +++ /dev/null @@ -1,211 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using Cohere with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "-NbXjAdlh0vJ", - "outputId": "fae77912-4e6a-4c78-fcb7-fbbe46f7a9c7" - }, - "outputs": [], - "source": [ - "!pip install embedchain[together]" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set Cohere related environment variables\n", - "\n", - "You can find `OPENAI_API_KEY` on your [OpenAI dashboard](https://platform.openai.com/account/api-keys) and `TOGETHER_API_KEY` key on your [Together dashboard](https://api.together.xyz/settings/api-keys)." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"OPENAI_API_KEY\"] = \"\"\n", - "os.environ[\"TOGETHER_API_KEY\"] = \"\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3 Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 321 - }, - "id": "Amzxk3m-i3tD", - "outputId": "afe8afde-5cb8-46bc-c541-3ad26cc3fa6e" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"provider\": \"together\",\n", - " \"config\": {\n", - " \"model\": \"mistralai/Mixtral-8x7B-Instruct-v0.1\",\n", - " \"temperature\": 0.5,\n", - " \"max_tokens\": 1000\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 176 - }, - "id": "Sn_0rx9QjIY9", - "outputId": "2f2718a4-3b7e-4844-fd46-3e0857653ca0" - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Inserting batches in chromadb: 100%|██████████| 1/1 [00:01<00:00, 1.16s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Successfully saved https://www.forbes.com/profile/elon-musk (DataType.WEB_PAGE). New chunks count: 4\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "text/plain": [ - "'8cf46026cabf9b05394a2658bd1fe890'" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "cvIK7dWRjN_f", - "outputId": "79e873c8-9594-45da-f5a3-0a893511267f" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/notebooks/vertex_ai.ipynb b/embedchain/notebooks/vertex_ai.ipynb deleted file mode 100644 index 1cb41a77a..000000000 --- a/embedchain/notebooks/vertex_ai.ipynb +++ /dev/null @@ -1,162 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "b02n_zJ_hl3d" - }, - "source": [ - "## Cookbook for using VertexAI with Embedchain" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gyJ6ui2vhtMY" - }, - "source": [ - "### Step-1: Install embedchain package" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "-NbXjAdlh0vJ", - "outputId": "eb9be5b6-dc81-43d2-d515-df8f0116be11" - }, - "outputs": [], - "source": [ - "!pip install embedchain[vertexai]" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nGnpSYAAh2bQ" - }, - "source": [ - "### Step-2: Set VertexAI related environment variables\n", - "\n", - "You can find `OPENAI_API_KEY` on your [OpenAI dashboard](https://platform.openai.com/account/api-keys)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "0fBdQ9GAiRvK" - }, - "outputs": [], - "source": [ - "import os\n", - "from embedchain import App\n", - "\n", - "os.environ[\"OPENAI_API_KEY\"] = \"sk-xxx\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "PGt6uPLIi1CS" - }, - "source": [ - "### Step-3 Create embedchain app and define your config" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 582 - }, - "id": "Amzxk3m-i3tD", - "outputId": "5084b6ea-ec20-4281-9f36-e21e93c17475" - }, - "outputs": [], - "source": [ - "app = App.from_config(config={\n", - " \"llm\": {\n", - " \"provider\": \"vertexai\",\n", - " \"config\": {\n", - " \"model\": \"chat-bison\",\n", - " \"temperature\": 0.5,\n", - " \"max_tokens\": 1000,\n", - " \"stream\": False\n", - " }\n", - " },\n", - " \"embedder\": {\n", - " \"provider\": \"vertexai\",\n", - " \"config\": {\n", - " \"model\": \"textembedding-gecko\"\n", - " }\n", - " }\n", - "})" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XNXv4yZwi7ef" - }, - "source": [ - "### Step-4: Add data sources to your app" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Sn_0rx9QjIY9" - }, - "outputs": [], - "source": [ - "app.add(\"https://www.forbes.com/profile/elon-musk\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7W6fDeAjMAP" - }, - "source": [ - "### Step-5: All set. Now start asking questions related to your data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "cvIK7dWRjN_f" - }, - "outputs": [], - "source": [ - "while(True):\n", - " question = input(\"Enter question: \")\n", - " if question in ['q', 'exit', 'quit']:\n", - " break\n", - " answer = app.query(question)\n", - " print(answer)" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/embedchain/poetry.lock b/embedchain/poetry.lock deleted file mode 100644 index 6c027b87b..000000000 --- a/embedchain/poetry.lock +++ /dev/null @@ -1,7589 +0,0 @@ -# This file is automatically @generated by Poetry 2.3.4 and should not be changed by hand. - -[[package]] -name = "aiohttp" -version = "3.9.5" -description = "Async http client/server framework (asyncio)" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcde4c397f673fdec23e6b05ebf8d4751314fa7c24f93334bf1f1364c1c69ac7"}, - {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d6b3f1fabe465e819aed2c421a6743d8debbde79b6a8600739300630a01bf2c"}, - {file = "aiohttp-3.9.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ae79c1bc12c34082d92bf9422764f799aee4746fd7a392db46b7fd357d4a17a"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d3ebb9e1316ec74277d19c5f482f98cc65a73ccd5430540d6d11682cd857430"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84dabd95154f43a2ea80deffec9cb44d2e301e38a0c9d331cc4aa0166fe28ae3"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8a02fbeca6f63cb1f0475c799679057fc9268b77075ab7cf3f1c600e81dd46b"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c26959ca7b75ff768e2776d8055bf9582a6267e24556bb7f7bd29e677932be72"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:714d4e5231fed4ba2762ed489b4aec07b2b9953cf4ee31e9871caac895a839c0"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7a6a8354f1b62e15d48e04350f13e726fa08b62c3d7b8401c0a1314f02e3558"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c413016880e03e69d166efb5a1a95d40f83d5a3a648d16486592c49ffb76d0db"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ff84aeb864e0fac81f676be9f4685f0527b660f1efdc40dcede3c251ef1e867f"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ad7f2919d7dac062f24d6f5fe95d401597fbb015a25771f85e692d043c9d7832"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:702e2c7c187c1a498a4e2b03155d52658fdd6fda882d3d7fbb891a5cf108bb10"}, - {file = "aiohttp-3.9.5-cp310-cp310-win32.whl", hash = "sha256:67c3119f5ddc7261d47163ed86d760ddf0e625cd6246b4ed852e82159617b5fb"}, - {file = "aiohttp-3.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:471f0ef53ccedec9995287f02caf0c068732f026455f07db3f01a46e49d76bbb"}, - {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342"}, - {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d"}, - {file = "aiohttp-3.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75"}, - {file = "aiohttp-3.9.5-cp311-cp311-win32.whl", hash = "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6"}, - {file = "aiohttp-3.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a"}, - {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678"}, - {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c"}, - {file = "aiohttp-3.9.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da"}, - {file = "aiohttp-3.9.5-cp312-cp312-win32.whl", hash = "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59"}, - {file = "aiohttp-3.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888"}, - {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:694d828b5c41255e54bc2dddb51a9f5150b4eefa9886e38b52605a05d96566e8"}, - {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0605cc2c0088fcaae79f01c913a38611ad09ba68ff482402d3410bf59039bfb8"}, - {file = "aiohttp-3.9.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4558e5012ee03d2638c681e156461d37b7a113fe13970d438d95d10173d25f78"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbc053ac75ccc63dc3a3cc547b98c7258ec35a215a92bd9f983e0aac95d3d5b"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4109adee842b90671f1b689901b948f347325045c15f46b39797ae1bf17019de"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6ea1a5b409a85477fd8e5ee6ad8f0e40bf2844c270955e09360418cfd09abac"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3c2890ca8c59ee683fd09adf32321a40fe1cf164e3387799efb2acebf090c11"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3916c8692dbd9d55c523374a3b8213e628424d19116ac4308e434dbf6d95bbdd"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8d1964eb7617907c792ca00b341b5ec3e01ae8c280825deadbbd678447b127e1"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5ab8e1f6bee051a4bf6195e38a5c13e5e161cb7bad83d8854524798bd9fcd6e"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:52c27110f3862a1afbcb2af4281fc9fdc40327fa286c4625dfee247c3ba90156"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7f64cbd44443e80094309875d4f9c71d0401e966d191c3d469cde4642bc2e031"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8b4f72fbb66279624bfe83fd5eb6aea0022dad8eec62b71e7bf63ee1caadeafe"}, - {file = "aiohttp-3.9.5-cp38-cp38-win32.whl", hash = "sha256:6380c039ec52866c06d69b5c7aad5478b24ed11696f0e72f6b807cfb261453da"}, - {file = "aiohttp-3.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:da22dab31d7180f8c3ac7c7635f3bcd53808f374f6aa333fe0b0b9e14b01f91a"}, - {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1732102949ff6087589408d76cd6dea656b93c896b011ecafff418c9661dc4ed"}, - {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6021d296318cb6f9414b48e6a439a7f5d1f665464da507e8ff640848ee2a58a"}, - {file = "aiohttp-3.9.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:239f975589a944eeb1bad26b8b140a59a3a320067fb3cd10b75c3092405a1372"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b7b30258348082826d274504fbc7c849959f1989d86c29bc355107accec6cfb"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2adf5c87ff6d8b277814a28a535b59e20bfea40a101db6b3bdca7e9926bc24"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a3d838441bebcf5cf442700e3963f58b5c33f015341f9ea86dcd7d503c07e2"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e3a1ae66e3d0c17cf65c08968a5ee3180c5a95920ec2731f53343fac9bad106"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c69e77370cce2d6df5d12b4e12bdcca60c47ba13d1cbbc8645dd005a20b738b"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf56238f4bbf49dab8c2dc2e6b1b68502b1e88d335bea59b3f5b9f4c001475"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d1469f228cd9ffddd396d9948b8c9cd8022b6d1bf1e40c6f25b0fb90b4f893ed"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:45731330e754f5811c314901cebdf19dd776a44b31927fa4b4dbecab9e457b0c"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3fcb4046d2904378e3aeea1df51f697b0467f2aac55d232c87ba162709478c46"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8cf142aa6c1a751fcb364158fd710b8a9be874b81889c2bd13aa8893197455e2"}, - {file = "aiohttp-3.9.5-cp39-cp39-win32.whl", hash = "sha256:7b179eea70833c8dee51ec42f3b4097bd6370892fa93f510f76762105568cf09"}, - {file = "aiohttp-3.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:38d80498e2e169bc61418ff36170e0aad0cd268da8b38a17c4cf29d254a8b3f1"}, - {file = "aiohttp-3.9.5.tar.gz", hash = "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551"}, -] - -[package.dependencies] -aiosignal = ">=1.1.2" -async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} -attrs = ">=17.3.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -yarl = ">=1.0,<2.0" - -[package.extras] -speedups = ["Brotli ; platform_python_implementation == \"CPython\"", "aiodns ; sys_platform == \"linux\" or sys_platform == \"darwin\"", "brotlicffi ; platform_python_implementation != \"CPython\""] - -[[package]] -name = "aiosignal" -version = "1.3.1" -description = "aiosignal: a list of registered asynchronous callbacks" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, -] - -[package.dependencies] -frozenlist = ">=1.1.0" - -[[package]] -name = "alembic" -version = "1.13.2" -description = "A database migration tool for SQLAlchemy." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "alembic-1.13.2-py3-none-any.whl", hash = "sha256:6b8733129a6224a9a711e17c99b08462dbf7cc9670ba8f2e2ae9af860ceb1953"}, - {file = "alembic-1.13.2.tar.gz", hash = "sha256:1ff0ae32975f4fd96028c39ed9bb3c867fe3af956bd7bb37343b54c9fe7445ef"}, -] - -[package.dependencies] -Mako = "*" -SQLAlchemy = ">=1.3.0" -typing-extensions = ">=4" - -[package.extras] -tz = ["backports.zoneinfo ; python_version < \"3.9\""] - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "anyio" -version = "4.4.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, - {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, -] - -[package.dependencies] -exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} -idna = ">=2.8" -sniffio = ">=1.1" -typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} - -[package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\""] -trio = ["trio (>=0.23)"] - -[[package]] -name = "asgiref" -version = "3.8.1" -description = "ASGI specs, helper code, and adapters" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"}, - {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""} - -[package.extras] -tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] - -[[package]] -name = "async-timeout" -version = "4.0.3" -description = "Timeout context manager for asyncio programs" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version < \"3.11\"" -files = [ - {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, - {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, -] - -[[package]] -name = "attrs" -version = "23.2.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, - {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, -] - -[package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-mypy = ["mypy (>=1.6) ; platform_python_implementation == \"CPython\" and python_version >= \"3.8\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.8\""] -tests-no-zope = ["attrs[tests-mypy]", "cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] - -[[package]] -name = "authlib" -version = "1.6.10" -description = "The ultimate Python library in building OAuth and OpenID Connect servers and clients." -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"weaviate\"" -files = [ - {file = "authlib-1.6.10-py2.py3-none-any.whl", hash = "sha256:aa639b43292554539924a3b4aaa9e81cd67ab64d3e28b22428c61f1200240287"}, - {file = "authlib-1.6.10.tar.gz", hash = "sha256:856a4f54d6ef3361ca6bb6d14a27e8b88f8097cca795fb428ffe13720e2ecde6"}, -] - -[package.dependencies] -cryptography = "*" - -[[package]] -name = "backoff" -version = "2.2.1" -description = "Function decoration for backoff and retry" -optional = false -python-versions = ">=3.7,<4.0" -groups = ["main"] -files = [ - {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, - {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, -] - -[[package]] -name = "bcrypt" -version = "4.1.3" -description = "Modern password hashing for your software and your servers" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "bcrypt-4.1.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:48429c83292b57bf4af6ab75809f8f4daf52aa5d480632e53707805cc1ce9b74"}, - {file = "bcrypt-4.1.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a8bea4c152b91fd8319fef4c6a790da5c07840421c2b785084989bf8bbb7455"}, - {file = "bcrypt-4.1.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d3b317050a9a711a5c7214bf04e28333cf528e0ed0ec9a4e55ba628d0f07c1a"}, - {file = "bcrypt-4.1.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:094fd31e08c2b102a14880ee5b3d09913ecf334cd604af27e1013c76831f7b05"}, - {file = "bcrypt-4.1.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:4fb253d65da30d9269e0a6f4b0de32bd657a0208a6f4e43d3e645774fb5457f3"}, - {file = "bcrypt-4.1.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:193bb49eeeb9c1e2db9ba65d09dc6384edd5608d9d672b4125e9320af9153a15"}, - {file = "bcrypt-4.1.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:8cbb119267068c2581ae38790e0d1fbae65d0725247a930fc9900c285d95725d"}, - {file = "bcrypt-4.1.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6cac78a8d42f9d120b3987f82252bdbeb7e6e900a5e1ba37f6be6fe4e3848286"}, - {file = "bcrypt-4.1.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:01746eb2c4299dd0ae1670234bf77704f581dd72cc180f444bfe74eb80495b64"}, - {file = "bcrypt-4.1.3-cp37-abi3-win32.whl", hash = "sha256:037c5bf7c196a63dcce75545c8874610c600809d5d82c305dd327cd4969995bf"}, - {file = "bcrypt-4.1.3-cp37-abi3-win_amd64.whl", hash = "sha256:8a893d192dfb7c8e883c4576813bf18bb9d59e2cfd88b68b725990f033f1b978"}, - {file = "bcrypt-4.1.3-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0d4cf6ef1525f79255ef048b3489602868c47aea61f375377f0d00514fe4a78c"}, - {file = "bcrypt-4.1.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5698ce5292a4e4b9e5861f7e53b1d89242ad39d54c3da451a93cac17b61921a"}, - {file = "bcrypt-4.1.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec3c2e1ca3e5c4b9edb94290b356d082b721f3f50758bce7cce11d8a7c89ce84"}, - {file = "bcrypt-4.1.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3a5be252fef513363fe281bafc596c31b552cf81d04c5085bc5dac29670faa08"}, - {file = "bcrypt-4.1.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5f7cd3399fbc4ec290378b541b0cf3d4398e4737a65d0f938c7c0f9d5e686611"}, - {file = "bcrypt-4.1.3-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:c4c8d9b3e97209dd7111bf726e79f638ad9224b4691d1c7cfefa571a09b1b2d6"}, - {file = "bcrypt-4.1.3-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:31adb9cbb8737a581a843e13df22ffb7c84638342de3708a98d5c986770f2834"}, - {file = "bcrypt-4.1.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:551b320396e1d05e49cc18dd77d970accd52b322441628aca04801bbd1d52a73"}, - {file = "bcrypt-4.1.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6717543d2c110a155e6821ce5670c1f512f602eabb77dba95717ca76af79867d"}, - {file = "bcrypt-4.1.3-cp39-abi3-win32.whl", hash = "sha256:6004f5229b50f8493c49232b8e75726b568535fd300e5039e255d919fc3a07f2"}, - {file = "bcrypt-4.1.3-cp39-abi3-win_amd64.whl", hash = "sha256:2505b54afb074627111b5a8dc9b6ae69d0f01fea65c2fcaea403448c503d3991"}, - {file = "bcrypt-4.1.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:cb9c707c10bddaf9e5ba7cdb769f3e889e60b7d4fea22834b261f51ca2b89fed"}, - {file = "bcrypt-4.1.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9f8ea645eb94fb6e7bea0cf4ba121c07a3a182ac52876493870033141aa687bc"}, - {file = "bcrypt-4.1.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f44a97780677e7ac0ca393bd7982b19dbbd8d7228c1afe10b128fd9550eef5f1"}, - {file = "bcrypt-4.1.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d84702adb8f2798d813b17d8187d27076cca3cd52fe3686bb07a9083930ce650"}, - {file = "bcrypt-4.1.3.tar.gz", hash = "sha256:2ee15dd749f5952fe3f0430d0ff6b74082e159c50332a1413d51b5689cf06623"}, -] - -[package.extras] -tests = ["pytest (>=3.2.1,!=3.3.0)"] -typecheck = ["mypy"] - -[[package]] -name = "beautifulsoup4" -version = "4.12.3" -description = "Screen-scraping library" -optional = false -python-versions = ">=3.6.0" -groups = ["main"] -files = [ - {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, - {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, -] - -[package.dependencies] -soupsieve = ">1.2" - -[package.extras] -cchardet = ["cchardet"] -chardet = ["chardet"] -charset-normalizer = ["charset-normalizer"] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[[package]] -name = "black" -version = "23.12.1" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, - {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, - {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, - {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, - {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, - {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, - {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, - {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, - {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, - {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, - {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, - {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, - {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, - {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, - {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, - {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, - {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, - {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, - {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, - {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, - {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, - {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4) ; sys_platform != \"win32\" or implementation_name != \"pypy\"", "aiohttp (>=3.7.4,!=3.9.0) ; sys_platform == \"win32\" and implementation_name == \"pypy\""] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "boto3" -version = "1.34.144" -description = "The AWS SDK for Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "boto3-1.34.144-py3-none-any.whl", hash = "sha256:b8433d481d50b68a0162c0379c0dd4aabfc3d1ad901800beb5b87815997511c1"}, - {file = "boto3-1.34.144.tar.gz", hash = "sha256:2f3e88b10b8fcc5f6100a9d74cd28230edc9d4fa226d99dd40a3ab38ac213673"}, -] - -[package.dependencies] -botocore = ">=1.34.144,<1.35.0" -jmespath = ">=0.7.1,<2.0.0" -s3transfer = ">=0.10.0,<0.11.0" - -[package.extras] -crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] - -[[package]] -name = "botocore" -version = "1.34.144" -description = "Low-level, data-driven core of boto 3." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "botocore-1.34.144-py3-none-any.whl", hash = "sha256:a2cf26e1bf10d5917a2285e50257bc44e94a1d16574f282f3274f7a5d8d1f08b"}, - {file = "botocore-1.34.144.tar.gz", hash = "sha256:4215db28d25309d59c99507f1f77df9089e5bebbad35f6e19c7c44ec5383a3e8"}, -] - -[package.dependencies] -jmespath = ">=0.7.1,<2.0.0" -python-dateutil = ">=2.1,<3.0.0" -urllib3 = [ - {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""}, - {version = ">=1.25.4,<1.27", markers = "python_version < \"3.10\""}, -] - -[package.extras] -crt = ["awscrt (==0.20.11)"] - -[[package]] -name = "build" -version = "1.2.1" -description = "A simple, correct Python build frontend" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "build-1.2.1-py3-none-any.whl", hash = "sha256:75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4"}, - {file = "build-1.2.1.tar.gz", hash = "sha256:526263f4870c26f26c433545579475377b2b7588b6f1eac76a001e873ae3e19d"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "os_name == \"nt\""} -importlib-metadata = {version = ">=4.6", markers = "python_full_version < \"3.10.2\""} -packaging = ">=19.1" -pyproject_hooks = "*" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} - -[package.extras] -docs = ["furo (>=2023.8.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"] -test = ["build[uv,virtualenv]", "filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0) ; python_version < \"3.10\"", "setuptools (>=56.0.0) ; python_version == \"3.10\"", "setuptools (>=56.0.0) ; python_version == \"3.11\"", "setuptools (>=67.8.0) ; python_version >= \"3.12\"", "wheel (>=0.36.0)"] -typing = ["build[uv]", "importlib-metadata (>=5.1)", "mypy (>=1.9.0,<1.10.0)", "tomli", "typing-extensions (>=3.7.4.3)"] -uv = ["uv (>=0.1.18)"] -virtualenv = ["virtualenv (>=20.0.35)"] - -[[package]] -name = "cachetools" -version = "5.3.3" -description = "Extensible memoizing collections and decorators" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, - {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, -] - -[[package]] -name = "certifi" -version = "2024.7.4" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -groups = ["main", "dev"] -files = [ - {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, - {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, -] - -[[package]] -name = "cffi" -version = "1.16.0" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"weaviate\" or platform_python_implementation == \"PyPy\"" -files = [ - {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, - {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, - {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, - {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, - {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, - {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, - {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, - {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, - {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, - {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, - {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, - {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, - {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, - {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, - {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "cfgv" -version = "3.4.0" -description = "Validate configuration and produce human readable error messages." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, - {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, -] - -[[package]] -name = "charset-normalizer" -version = "3.3.2" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7.0" -groups = ["main", "dev"] -files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, -] - -[[package]] -name = "chroma-hnswlib" -version = "0.7.6" -description = "Chromas fork of hnswlib" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "chroma_hnswlib-0.7.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f35192fbbeadc8c0633f0a69c3d3e9f1a4eab3a46b65458bbcbcabdd9e895c36"}, - {file = "chroma_hnswlib-0.7.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f007b608c96362b8f0c8b6b2ac94f67f83fcbabd857c378ae82007ec92f4d82"}, - {file = "chroma_hnswlib-0.7.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:456fd88fa0d14e6b385358515aef69fc89b3c2191706fd9aee62087b62aad09c"}, - {file = "chroma_hnswlib-0.7.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5dfaae825499c2beaa3b75a12d7ec713b64226df72a5c4097203e3ed532680da"}, - {file = "chroma_hnswlib-0.7.6-cp310-cp310-win_amd64.whl", hash = "sha256:2487201982241fb1581be26524145092c95902cb09fc2646ccfbc407de3328ec"}, - {file = "chroma_hnswlib-0.7.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:81181d54a2b1e4727369486a631f977ffc53c5533d26e3d366dda243fb0998ca"}, - {file = "chroma_hnswlib-0.7.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4b4ab4e11f1083dd0a11ee4f0e0b183ca9f0f2ed63ededba1935b13ce2b3606f"}, - {file = "chroma_hnswlib-0.7.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53db45cd9173d95b4b0bdccb4dbff4c54a42b51420599c32267f3abbeb795170"}, - {file = "chroma_hnswlib-0.7.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c093f07a010b499c00a15bc9376036ee4800d335360570b14f7fe92badcdcf9"}, - {file = "chroma_hnswlib-0.7.6-cp311-cp311-win_amd64.whl", hash = "sha256:0540b0ac96e47d0aa39e88ea4714358ae05d64bbe6bf33c52f316c664190a6a3"}, - {file = "chroma_hnswlib-0.7.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e87e9b616c281bfbe748d01705817c71211613c3b063021f7ed5e47173556cb7"}, - {file = "chroma_hnswlib-0.7.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ec5ca25bc7b66d2ecbf14502b5729cde25f70945d22f2aaf523c2d747ea68912"}, - {file = "chroma_hnswlib-0.7.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:305ae491de9d5f3c51e8bd52d84fdf2545a4a2bc7af49765cda286b7bb30b1d4"}, - {file = "chroma_hnswlib-0.7.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:822ede968d25a2c88823ca078a58f92c9b5c4142e38c7c8b4c48178894a0a3c5"}, - {file = "chroma_hnswlib-0.7.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2fe6ea949047beed19a94b33f41fe882a691e58b70c55fdaa90274ae78be046f"}, - {file = "chroma_hnswlib-0.7.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feceff971e2a2728c9ddd862a9dd6eb9f638377ad98438876c9aeac96c9482f5"}, - {file = "chroma_hnswlib-0.7.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb0633b60e00a2b92314d0bf5bbc0da3d3320be72c7e3f4a9b19f4609dc2b2ab"}, - {file = "chroma_hnswlib-0.7.6-cp37-cp37m-win_amd64.whl", hash = "sha256:a566abe32fab42291f766d667bdbfa234a7f457dcbd2ba19948b7a978c8ca624"}, - {file = "chroma_hnswlib-0.7.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6be47853d9a58dedcfa90fc846af202b071f028bbafe1d8711bf64fe5a7f6111"}, - {file = "chroma_hnswlib-0.7.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3a7af35bdd39a88bffa49f9bb4bf4f9040b684514a024435a1ef5cdff980579d"}, - {file = "chroma_hnswlib-0.7.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a53b1f1551f2b5ad94eb610207bde1bb476245fc5097a2bec2b476c653c58bde"}, - {file = "chroma_hnswlib-0.7.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3085402958dbdc9ff5626ae58d696948e715aef88c86d1e3f9285a88f1afd3bc"}, - {file = "chroma_hnswlib-0.7.6-cp38-cp38-win_amd64.whl", hash = "sha256:77326f658a15adfb806a16543f7db7c45f06fd787d699e643642d6bde8ed49c4"}, - {file = "chroma_hnswlib-0.7.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:93b056ab4e25adab861dfef21e1d2a2756b18be5bc9c292aa252fa12bb44e6ae"}, - {file = "chroma_hnswlib-0.7.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fe91f018b30452c16c811fd6c8ede01f84e5a9f3c23e0758775e57f1c3778871"}, - {file = "chroma_hnswlib-0.7.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6c0e627476f0f4d9e153420d36042dd9c6c3671cfd1fe511c0253e38c2a1039"}, - {file = "chroma_hnswlib-0.7.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e9796a4536b7de6c6d76a792ba03e08f5aaa53e97e052709568e50b4d20c04f"}, - {file = "chroma_hnswlib-0.7.6-cp39-cp39-win_amd64.whl", hash = "sha256:d30e2db08e7ffdcc415bd072883a322de5995eb6ec28a8f8c054103bbd3ec1e0"}, - {file = "chroma_hnswlib-0.7.6.tar.gz", hash = "sha256:4dce282543039681160259d29fcde6151cc9106c6461e0485f57cdccd83059b7"}, -] - -[package.dependencies] -numpy = "*" - -[[package]] -name = "chromadb" -version = "0.5.18" -description = "Chroma." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "chromadb-0.5.18-py3-none-any.whl", hash = "sha256:9dd3827b5e04b4ff0a5ea0df28a78bac88a09f45be37fcd7fe20f879b57c43cf"}, - {file = "chromadb-0.5.18.tar.gz", hash = "sha256:cfbb3e5aeeb1dd532b47d80ed9185e8a9886c09af41c8e6123edf94395d76aec"}, -] - -[package.dependencies] -bcrypt = ">=4.0.1" -build = ">=1.0.3" -chroma-hnswlib = "0.7.6" -fastapi = ">=0.95.2" -grpcio = ">=1.58.0" -httpx = ">=0.27.0" -importlib-resources = "*" -kubernetes = ">=28.1.0" -mmh3 = ">=4.0.1" -numpy = ">=1.22.5" -onnxruntime = ">=1.14.1" -opentelemetry-api = ">=1.2.0" -opentelemetry-exporter-otlp-proto-grpc = ">=1.2.0" -opentelemetry-instrumentation-fastapi = ">=0.41b0" -opentelemetry-sdk = ">=1.2.0" -orjson = ">=3.9.12" -overrides = ">=7.3.1" -posthog = ">=2.4.0" -pydantic = ">=1.9" -pypika = ">=0.48.9" -PyYAML = ">=6.0.0" -rich = ">=10.11.0" -tenacity = ">=8.2.3" -tokenizers = ">=0.13.2" -tqdm = ">=4.65.0" -typer = ">=0.9.0" -typing-extensions = ">=4.5.0" -uvicorn = {version = ">=0.18.3", extras = ["standard"]} - -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "cohere" -version = "5.5.8" -description = "" -optional = false -python-versions = "<4.0,>=3.8" -groups = ["main"] -files = [ - {file = "cohere-5.5.8-py3-none-any.whl", hash = "sha256:e1ed84b90eadd13c6a68ee28e378a0bb955f8945eadc6eb7ee126b3399cafd54"}, - {file = "cohere-5.5.8.tar.gz", hash = "sha256:84ce7666ff8fbdf4f41fb5f6ca452ab2639a514bc88967a2854a9b1b820d6ea0"}, -] - -[package.dependencies] -boto3 = ">=1.34.0,<2.0.0" -fastavro = ">=1.9.4,<2.0.0" -httpx = ">=0.21.2" -httpx-sse = ">=0.4.0,<0.5.0" -parameterized = ">=0.9.0,<0.10.0" -pydantic = ">=1.9.2" -requests = ">=2.0.0,<3.0.0" -tokenizers = ">=0.15,<1" -types-requests = ">=2.0.0,<3.0.0" -typing_extensions = ">=4.0.0" - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev"] -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -markers = {main = "platform_system == \"Windows\" or os_name == \"nt\" or sys_platform == \"win32\"", dev = "platform_system == \"Windows\" or sys_platform == \"win32\""} - -[[package]] -name = "coloredlogs" -version = "15.0.1" -description = "Colored terminal output for Python's logging module" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main"] -files = [ - {file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"}, - {file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"}, -] - -[package.dependencies] -humanfriendly = ">=9.1" - -[package.extras] -cron = ["capturer (>=2.4)"] - -[[package]] -name = "coverage" -version = "7.6.0" -description = "Code coverage measurement for Python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "coverage-7.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dff044f661f59dace805eedb4a7404c573b6ff0cdba4a524141bc63d7be5c7fd"}, - {file = "coverage-7.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8659fd33ee9e6ca03950cfdcdf271d645cf681609153f218826dd9805ab585c"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7792f0ab20df8071d669d929c75c97fecfa6bcab82c10ee4adb91c7a54055463"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4b3cd1ca7cd73d229487fa5caca9e4bc1f0bca96526b922d61053ea751fe791"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7e128f85c0b419907d1f38e616c4f1e9f1d1b37a7949f44df9a73d5da5cd53c"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a94925102c89247530ae1dab7dc02c690942566f22e189cbd53579b0693c0783"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dcd070b5b585b50e6617e8972f3fbbee786afca71b1936ac06257f7e178f00f6"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d50a252b23b9b4dfeefc1f663c568a221092cbaded20a05a11665d0dbec9b8fb"}, - {file = "coverage-7.6.0-cp310-cp310-win32.whl", hash = "sha256:0e7b27d04131c46e6894f23a4ae186a6a2207209a05df5b6ad4caee6d54a222c"}, - {file = "coverage-7.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dece71673b3187c86226c3ca793c5f891f9fc3d8aa183f2e3653da18566169"}, - {file = "coverage-7.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7b525ab52ce18c57ae232ba6f7010297a87ced82a2383b1afd238849c1ff933"}, - {file = "coverage-7.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bea27c4269234e06f621f3fac3925f56ff34bc14521484b8f66a580aacc2e7d"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed8d1d1821ba5fc88d4a4f45387b65de52382fa3ef1f0115a4f7a20cdfab0e94"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03cafe82c1b32b770a29fd6de923625ccac3185a54a5e66606da26d105f37dac"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d1b923fc4a40c5832be4f35a5dab0e5ff89cddf83bb4174499e02ea089daf57"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4b03741e70fb811d1a9a1d75355cf391f274ed85847f4b78e35459899f57af4d"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a73d18625f6a8a1cbb11eadc1d03929f9510f4131879288e3f7922097a429f63"}, - {file = "coverage-7.6.0-cp311-cp311-win32.whl", hash = "sha256:65fa405b837060db569a61ec368b74688f429b32fa47a8929a7a2f9b47183713"}, - {file = "coverage-7.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:6379688fb4cfa921ae349c76eb1a9ab26b65f32b03d46bb0eed841fd4cb6afb1"}, - {file = "coverage-7.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f7db0b6ae1f96ae41afe626095149ecd1b212b424626175a6633c2999eaad45b"}, - {file = "coverage-7.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bbdf9a72403110a3bdae77948b8011f644571311c2fb35ee15f0f10a8fc082e8"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc44bf0315268e253bf563f3560e6c004efe38f76db03a1558274a6e04bf5d5"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da8549d17489cd52f85a9829d0e1d91059359b3c54a26f28bec2c5d369524807"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fad32ee9b27350687035cb5fdf9145bc9cf0a094a9577d43e909948ebcfa27b"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:044a0985a4f25b335882b0966625270a8d9db3d3409ddc49a4eb00b0ef5e8cee"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:76d5f82213aa78098b9b964ea89de4617e70e0d43e97900c2778a50856dac605"}, - {file = "coverage-7.6.0-cp312-cp312-win32.whl", hash = "sha256:3c59105f8d58ce500f348c5b56163a4113a440dad6daa2294b5052a10db866da"}, - {file = "coverage-7.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:ca5d79cfdae420a1d52bf177de4bc2289c321d6c961ae321503b2ca59c17ae67"}, - {file = "coverage-7.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d39bd10f0ae453554798b125d2f39884290c480f56e8a02ba7a6ed552005243b"}, - {file = "coverage-7.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:beb08e8508e53a568811016e59f3234d29c2583f6b6e28572f0954a6b4f7e03d"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2e16f4cd2bc4d88ba30ca2d3bbf2f21f00f382cf4e1ce3b1ddc96c634bc48ca"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6616d1c9bf1e3faea78711ee42a8b972367d82ceae233ec0ac61cc7fec09fa6b"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4567d6c334c46046d1c4c20024de2a1c3abc626817ae21ae3da600f5779b44"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d17c6a415d68cfe1091d3296ba5749d3d8696e42c37fca5d4860c5bf7b729f03"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9146579352d7b5f6412735d0f203bbd8d00113a680b66565e205bc605ef81bc6"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cdab02a0a941af190df8782aafc591ef3ad08824f97850b015c8c6a8b3877b0b"}, - {file = "coverage-7.6.0-cp38-cp38-win32.whl", hash = "sha256:df423f351b162a702c053d5dddc0fc0ef9a9e27ea3f449781ace5f906b664428"}, - {file = "coverage-7.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:f2501d60d7497fd55e391f423f965bbe9e650e9ffc3c627d5f0ac516026000b8"}, - {file = "coverage-7.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7221f9ac9dad9492cecab6f676b3eaf9185141539d5c9689d13fd6b0d7de840c"}, - {file = "coverage-7.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ddaaa91bfc4477d2871442bbf30a125e8fe6b05da8a0015507bfbf4718228ab2"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4cbe651f3904e28f3a55d6f371203049034b4ddbce65a54527a3f189ca3b390"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:831b476d79408ab6ccfadaaf199906c833f02fdb32c9ab907b1d4aa0713cfa3b"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46c3d091059ad0b9c59d1034de74a7f36dcfa7f6d3bde782c49deb42438f2450"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4d5fae0a22dc86259dee66f2cc6c1d3e490c4a1214d7daa2a93d07491c5c04b6"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:07ed352205574aad067482e53dd606926afebcb5590653121063fbf4e2175166"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:49c76cdfa13015c4560702574bad67f0e15ca5a2872c6a125f6327ead2b731dd"}, - {file = "coverage-7.6.0-cp39-cp39-win32.whl", hash = "sha256:482855914928c8175735a2a59c8dc5806cf7d8f032e4820d52e845d1f731dca2"}, - {file = "coverage-7.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:543ef9179bc55edfd895154a51792b01c017c87af0ebaae092720152e19e42ca"}, - {file = "coverage-7.6.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:6fe885135c8a479d3e37a7aae61cbd3a0fb2deccb4dda3c25f92a49189f766d6"}, - {file = "coverage-7.6.0.tar.gz", hash = "sha256:289cc803fa1dc901f84701ac10c9ee873619320f2f9aff38794db4a4a0268d51"}, -] - -[package.dependencies] -tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} - -[package.extras] -toml = ["tomli ; python_full_version <= \"3.11.0a6\""] - -[[package]] -name = "cryptography" -version = "42.0.8" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = true -python-versions = ">=3.7" -groups = ["main"] -markers = "extra == \"weaviate\"" -files = [ - {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, - {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"}, - {file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"}, - {file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"}, - {file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"}, - {file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"}, - {file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"}, - {file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"}, -] - -[package.dependencies] -cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] -nox = ["nox"] -pep8test = ["check-sdist", "click", "mypy", "ruff"] -sdist = ["build"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] -test-randomorder = ["pytest-randomly"] - -[[package]] -name = "cuda-bindings" -version = "13.2.0" -description = "Python bindings for CUDA" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and python_version >= \"3.10\"" -files = [ - {file = "cuda_bindings-13.2.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08b395f79cb89ce0cd8effff07c4a1e20101b873c256a1aeb286e8fd7bd0f556"}, - {file = "cuda_bindings-13.2.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6f3682ec3c4769326aafc67c2ba669d97d688d0b7e63e659d36d2f8b72f32d6"}, - {file = "cuda_bindings-13.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:845025438a1b9e20718b9fb42add3e0eb72e85458bcab3eeb80bfd8f0a9dab33"}, - {file = "cuda_bindings-13.2.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:721104c603f059780d287969be3d194a18d0cc3b713ed9049065a1107706759d"}, - {file = "cuda_bindings-13.2.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1eba9504ac70667dd48313395fe05157518fd6371b532790e96fbb31bbb5a5e1"}, - {file = "cuda_bindings-13.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:debb51b211d246f8326f6b6e982506a5d0d9906672c91bc478b66addc7ecc60a"}, - {file = "cuda_bindings-13.2.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e865447abfb83d6a98ad5130ed3c70b1fc295ae3eeee39fd07b4ddb0671b6788"}, - {file = "cuda_bindings-13.2.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:46d8776a55d6d5da9dd6e9858fba2efcda2abe6743871dee47dd06eb8cb6d955"}, - {file = "cuda_bindings-13.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:45815daeb595bf3b405c52671a2542b1f8e9329f3b029494acbfcc74aeaa1f2d"}, - {file = "cuda_bindings-13.2.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6629ca2df6f795b784752409bcaedbd22a7a651b74b56a165ebc0c9dcbd504d0"}, - {file = "cuda_bindings-13.2.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7dca0da053d3b4cc4869eff49c61c03f3c5dbaa0bcd712317a358d5b8f3f385d"}, - {file = "cuda_bindings-13.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8cebe3ce4aeeca5af9c490e175f76c4b569bbf4a35a62294b777bc77bf7ac4d8"}, - {file = "cuda_bindings-13.2.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a6464b30f46692d6c7f65d4a0e0450d81dd29de3afc1bb515653973d01c2cd6e"}, - {file = "cuda_bindings-13.2.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f4af9f3e1be603fa12d5ad6cfca7844c9d230befa9792b5abdf7dd79979c3626"}, - {file = "cuda_bindings-13.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:bd658bb5c0e55b7b3e5dd0ed509c6addb298c665db26a9bfba35e1e626000ba2"}, - {file = "cuda_bindings-13.2.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df850a1ff8ce1b3385257b08e47b70e959932f5f432d0a4e46a355962b4e4771"}, - {file = "cuda_bindings-13.2.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8a16384c6494e5485f39314b0b4afb04bee48d49edb16d5d8593fd35bbd231b"}, - {file = "cuda_bindings-13.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6ccf14e0c1def3b7200100aafff3a9f7e210ecb6e409329e92dcf6cd2c00d5c7"}, -] - -[package.dependencies] -cuda-pathfinder = ">=1.1,<2.0" - -[package.extras] -all = ["cuda-toolkit[cufile] (==13.*) ; sys_platform == \"linux\"", "cuda-toolkit[nvfatbin,nvjitlink,nvrtc,nvvm] (==13.*)"] - -[[package]] -name = "cuda-pathfinder" -version = "1.5.3" -description = "Pathfinder for CUDA components" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and python_version >= \"3.10\"" -files = [ - {file = "cuda_pathfinder-1.5.3-py3-none-any.whl", hash = "sha256:dff021123aedbb4117cc7ec81717bbfe198fb4e8b5f1ee57e0e084fec5c8577d"}, -] - -[[package]] -name = "cuda-toolkit" -version = "13.0.2" -description = "CUDA Toolkit meta-package" -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and python_version >= \"3.10\"" -files = [ - {file = "cuda_toolkit-13.0.2-py2.py3-none-any.whl", hash = "sha256:b198824cf2f54003f50d64ada3a0f184b42ca0846c1c94192fa269ecd97a66eb"}, -] - -[package.dependencies] -nvidia-cublas = {version = "==13.1.0.3.*", optional = true, markers = "(sys_platform == \"linux\" or sys_platform == \"win32\") and extra == \"cublas\""} -nvidia-cuda-cupti = {version = "==13.0.85.*", optional = true, markers = "(sys_platform == \"linux\" or sys_platform == \"win32\") and extra == \"cupti\""} -nvidia-cuda-nvrtc = {version = "==13.0.88.*", optional = true, markers = "(sys_platform == \"linux\" or sys_platform == \"win32\") and extra == \"nvrtc\""} -nvidia-cuda-runtime = {version = "==13.0.96.*", optional = true, markers = "(sys_platform == \"linux\" or sys_platform == \"win32\") and extra == \"cudart\""} -nvidia-cufft = {version = "==12.0.0.61.*", optional = true, markers = "(sys_platform == \"linux\" or sys_platform == \"win32\") and extra == \"cufft\""} -nvidia-cufile = {version = "==1.15.1.6.*", optional = true, markers = "sys_platform == \"linux\" and extra == \"cufile\""} -nvidia-curand = {version = "==10.4.0.35.*", optional = true, markers = "(sys_platform == \"linux\" or sys_platform == \"win32\") and extra == \"curand\""} -nvidia-cusolver = {version = "==12.0.4.66.*", optional = true, markers = "(sys_platform == \"linux\" or sys_platform == \"win32\") and extra == \"cusolver\""} -nvidia-cusparse = {version = "==12.6.3.3.*", optional = true, markers = "(sys_platform == \"linux\" or sys_platform == \"win32\") and extra == \"cusparse\""} -nvidia-nvjitlink = {version = "==13.0.88.*", optional = true, markers = "(sys_platform == \"linux\" or sys_platform == \"win32\") and extra == \"nvjitlink\""} -nvidia-nvtx = {version = "==13.0.85.*", optional = true, markers = "(sys_platform == \"linux\" or sys_platform == \"win32\") and extra == \"nvtx\""} - -[package.extras] -all = ["nvidia-cublas (==13.1.0.3.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cuda-cccl (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cuda-crt (==13.0.88.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cuda-culibos (==13.0.85.*) ; sys_platform == \"linux\"", "nvidia-cuda-cupti (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cuda-cuxxfilt (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cuda-nvcc (==13.0.88.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cuda-nvrtc (==13.0.88.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cuda-opencl (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cuda-profiler-api (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cuda-runtime (==13.0.96.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cuda-sanitizer-api (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cufft (==12.0.0.61.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cufile (==1.15.1.6.*) ; sys_platform == \"linux\"", "nvidia-curand (==10.4.0.35.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cusolver (==12.0.4.66.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-cusparse (==12.6.3.3.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-npp (==13.0.1.2.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-nvfatbin (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-nvjitlink (==13.0.88.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-nvjpeg (==13.0.1.86.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-nvml-dev (==13.0.87.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-nvptxcompiler (==13.0.88.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-nvtx (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\"", "nvidia-nvvm (==13.0.88.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -cccl = ["nvidia-cuda-cccl (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -crt = ["nvidia-cuda-crt (==13.0.88.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -cublas = ["nvidia-cublas (==13.1.0.3.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -cudart = ["nvidia-cuda-runtime (==13.0.96.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -cufft = ["nvidia-cufft (==12.0.0.61.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -cufile = ["nvidia-cufile (==1.15.1.6.*) ; sys_platform == \"linux\""] -culibos = ["nvidia-cuda-culibos (==13.0.85.*) ; sys_platform == \"linux\""] -cupti = ["nvidia-cuda-cupti (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -curand = ["nvidia-curand (==10.4.0.35.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -cusolver = ["nvidia-cusolver (==12.0.4.66.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -cusparse = ["nvidia-cusparse (==12.6.3.3.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -cuxxfilt = ["nvidia-cuda-cuxxfilt (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -npp = ["nvidia-npp (==13.0.1.2.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -nvcc = ["nvidia-cuda-nvcc (==13.0.88.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -nvfatbin = ["nvidia-nvfatbin (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -nvjitlink = ["nvidia-nvjitlink (==13.0.88.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -nvjpeg = ["nvidia-nvjpeg (==13.0.1.86.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -nvml = ["nvidia-nvml-dev (==13.0.87.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -nvptxcompiler = ["nvidia-nvptxcompiler (==13.0.88.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -nvrtc = ["nvidia-cuda-nvrtc (==13.0.88.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -nvtx = ["nvidia-nvtx (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -nvvm = ["nvidia-nvvm (==13.0.88.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -opencl = ["nvidia-cuda-opencl (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -profiler = ["nvidia-cuda-profiler-api (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] -sanitizer = ["nvidia-cuda-sanitizer-api (==13.0.85.*) ; sys_platform == \"linux\" or sys_platform == \"win32\""] - -[[package]] -name = "dataclasses-json" -version = "0.6.7" -description = "Easily serialize dataclasses to and from JSON." -optional = false -python-versions = "<4.0,>=3.7" -groups = ["main"] -files = [ - {file = "dataclasses_json-0.6.7-py3-none-any.whl", hash = "sha256:0dbf33f26c8d5305befd61b39d2b3414e8a407bedc2834dea9b8d642666fb40a"}, - {file = "dataclasses_json-0.6.7.tar.gz", hash = "sha256:b6b3e528266ea45b9535223bc53ca645f5208833c29229e847b3f26a1cc55fc0"}, -] - -[package.dependencies] -marshmallow = ">=3.18.0,<4.0.0" -typing-inspect = ">=0.4.0,<1" - -[[package]] -name = "decorator" -version = "5.1.1" -description = "Decorators for Humans" -optional = true -python-versions = ">=3.5" -groups = ["main"] -markers = "extra == \"lancedb\"" -files = [ - {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, - {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, -] - -[[package]] -name = "deprecated" -version = "1.2.14" -description = "Python @deprecated decorator to deprecate old python classes, functions or methods." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -files = [ - {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, - {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, -] - -[package.dependencies] -wrapt = ">=1.10,<2" - -[package.extras] -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] - -[[package]] -name = "deprecation" -version = "2.1.0" -description = "A library to handle automated deprecations" -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"lancedb\"" -files = [ - {file = "deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a"}, - {file = "deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff"}, -] - -[package.dependencies] -packaging = "*" - -[[package]] -name = "distlib" -version = "0.3.8" -description = "Distribution utilities" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, - {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, -] - -[[package]] -name = "distro" -version = "1.9.0" -description = "Distro - an OS platform information API" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, - {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, -] - -[[package]] -name = "docstring-parser" -version = "0.16" -description = "Parse Python docstrings in reST, Google and Numpydoc format" -optional = true -python-versions = ">=3.6,<4.0" -groups = ["main"] -files = [ - {file = "docstring_parser-0.16-py3-none-any.whl", hash = "sha256:bf0a1387354d3691d102edef7ec124f219ef639982d096e26e3b60aeffa90637"}, - {file = "docstring_parser-0.16.tar.gz", hash = "sha256:538beabd0af1e2db0146b6bd3caa526c35a34d61af9fd2887f3a8a27a739aa6e"}, -] - -[[package]] -name = "elastic-transport" -version = "8.13.1" -description = "Transport classes and utilities shared among Python Elastic client libraries" -optional = true -python-versions = ">=3.7" -groups = ["main"] -markers = "extra == \"elasticsearch\"" -files = [ - {file = "elastic_transport-8.13.1-py3-none-any.whl", hash = "sha256:5d4bb6b8e9d74a9c16de274e91a5caf65a3a8d12876f1e99152975e15b2746fe"}, - {file = "elastic_transport-8.13.1.tar.gz", hash = "sha256:16339d392b4bbe86ad00b4bdeecff10edf516d32bc6c16053846625f2c6ea250"}, -] - -[package.dependencies] -certifi = "*" -urllib3 = ">=1.26.2,<3" - -[package.extras] -develop = ["aiohttp", "furo", "httpx", "mock", "opentelemetry-api", "opentelemetry-sdk", "orjson", "pytest", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "pytest-mock", "requests", "respx", "sphinx (>2)", "sphinx-autodoc-typehints", "trustme"] - -[[package]] -name = "elasticsearch" -version = "8.14.0" -description = "Python client for Elasticsearch" -optional = true -python-versions = ">=3.7" -groups = ["main"] -markers = "extra == \"elasticsearch\"" -files = [ - {file = "elasticsearch-8.14.0-py3-none-any.whl", hash = "sha256:cef8ef70a81af027f3da74a4f7d9296b390c636903088439087b8262a468c130"}, - {file = "elasticsearch-8.14.0.tar.gz", hash = "sha256:aa2490029dd96f4015b333c1827aa21fd6c0a4d223b00dfb0fe933b8d09a511b"}, -] - -[package.dependencies] -elastic-transport = ">=8.13,<9" - -[package.extras] -async = ["aiohttp (>=3,<4)"] -orjson = ["orjson (>=3)"] -requests = ["requests (>=2.4.0,!=2.32.2,<3.0.0)"] -vectorstore-mmr = ["numpy (>=1)", "simsimd (>=3)"] - -[[package]] -name = "environs" -version = "9.5.0" -description = "simplified environment variable parsing" -optional = true -python-versions = ">=3.6" -groups = ["main"] -markers = "extra == \"milvus\"" -files = [ - {file = "environs-9.5.0-py2.py3-none-any.whl", hash = "sha256:1e549569a3de49c05f856f40bce86979e7d5ffbbc4398e7f338574c220189124"}, - {file = "environs-9.5.0.tar.gz", hash = "sha256:a76307b36fbe856bdca7ee9161e6c466fd7fcffc297109a118c59b54e27e30c9"}, -] - -[package.dependencies] -marshmallow = ">=3.0.0" -python-dotenv = "*" - -[package.extras] -dev = ["dj-database-url", "dj-email-url", "django-cache-url", "flake8 (==4.0.1)", "flake8-bugbear (==21.9.2)", "mypy (==0.910)", "pre-commit (>=2.4,<3.0)", "pytest", "tox"] -django = ["dj-database-url", "dj-email-url", "django-cache-url"] -lint = ["flake8 (==4.0.1)", "flake8-bugbear (==21.9.2)", "mypy (==0.910)", "pre-commit (>=2.4,<3.0)"] -tests = ["dj-database-url", "dj-email-url", "django-cache-url", "pytest"] - -[[package]] -name = "eval-type-backport" -version = "0.2.0" -description = "Like `typing._eval_type`, but lets older Python versions use newer typing features." -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"together\"" -files = [ - {file = "eval_type_backport-0.2.0-py3-none-any.whl", hash = "sha256:ac2f73d30d40c5a30a80b8739a789d6bb5e49fdffa66d7912667e2015d9c9933"}, - {file = "eval_type_backport-0.2.0.tar.gz", hash = "sha256:68796cfbc7371ebf923f03bdf7bef415f3ec098aeced24e054b253a0e78f7b37"}, -] - -[package.extras] -tests = ["pytest"] - -[[package]] -name = "exceptiongroup" -version = "1.2.2" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -markers = "python_version < \"3.11\"" -files = [ - {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, - {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, -] - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "fastapi" -version = "0.110.3" -description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "fastapi-0.110.3-py3-none-any.whl", hash = "sha256:fd7600612f755e4050beb74001310b5a7e1796d149c2ee363124abdfa0289d32"}, - {file = "fastapi-0.110.3.tar.gz", hash = "sha256:555700b0159379e94fdbfc6bb66a0f1c43f4cf7060f25239af3d84b63a656626"}, -] - -[package.dependencies] -pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" -starlette = ">=0.37.2,<0.38.0" -typing-extensions = ">=4.8.0" - -[package.extras] -all = ["email_validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] - -[[package]] -name = "fastavro" -version = "1.9.5" -description = "Fast read/write of AVRO files" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "fastavro-1.9.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:61253148e95dd2b6457247b441b7555074a55de17aef85f5165bfd5facf600fc"}, - {file = "fastavro-1.9.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b604935d671ad47d888efc92a106f98e9440874108b444ac10e28d643109c937"}, - {file = "fastavro-1.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0adbf4956fd53bd74c41e7855bb45ccce953e0eb0e44f5836d8d54ad843f9944"}, - {file = "fastavro-1.9.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:53d838e31457db8bf44460c244543f75ed307935d5fc1d93bc631cc7caef2082"}, - {file = "fastavro-1.9.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:07b6288e8681eede16ff077632c47395d4925c2f51545cd7a60f194454db2211"}, - {file = "fastavro-1.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:ef08cf247fdfd61286ac0c41854f7194f2ad05088066a756423d7299b688d975"}, - {file = "fastavro-1.9.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c52d7bb69f617c90935a3e56feb2c34d4276819a5c477c466c6c08c224a10409"}, - {file = "fastavro-1.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85e05969956003df8fa4491614bc62fe40cec59e94d06e8aaa8d8256ee3aab82"}, - {file = "fastavro-1.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06e6df8527493a9f0d9a8778df82bab8b1aa6d80d1b004e5aec0a31dc4dc501c"}, - {file = "fastavro-1.9.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:27820da3b17bc01cebb6d1687c9d7254b16d149ef458871aaa207ed8950f3ae6"}, - {file = "fastavro-1.9.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:195a5b8e33eb89a1a9b63fa9dce7a77d41b3b0cd785bac6044df619f120361a2"}, - {file = "fastavro-1.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:be612c109efb727bfd36d4d7ed28eb8e0506617b7dbe746463ebbf81e85eaa6b"}, - {file = "fastavro-1.9.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b133456c8975ec7d2a99e16a7e68e896e45c821b852675eac4ee25364b999c14"}, - {file = "fastavro-1.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf586373c3d1748cac849395aad70c198ee39295f92e7c22c75757b5c0300fbe"}, - {file = "fastavro-1.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:724ef192bc9c55d5b4c7df007f56a46a21809463499856349d4580a55e2b914c"}, - {file = "fastavro-1.9.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bfd11fe355a8f9c0416803afac298960eb4c603a23b1c74ff9c1d3e673ea7185"}, - {file = "fastavro-1.9.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9827d1654d7bcb118ef5efd3e5b2c9ab2a48d44dac5e8c6a2327bc3ac3caa828"}, - {file = "fastavro-1.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:d84b69dca296667e6137ae7c9a96d060123adbc0c00532cc47012b64d38b47e9"}, - {file = "fastavro-1.9.5-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:fb744e9de40fb1dc75354098c8db7da7636cba50a40f7bef3b3fb20f8d189d88"}, - {file = "fastavro-1.9.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:240df8bacd13ff5487f2465604c007d686a566df5cbc01d0550684eaf8ff014a"}, - {file = "fastavro-1.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3bb35c25bbc3904e1c02333bc1ae0173e0a44aa37a8e95d07e681601246e1f1"}, - {file = "fastavro-1.9.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:b47a54a9700de3eabefd36dabfb237808acae47bc873cada6be6990ef6b165aa"}, - {file = "fastavro-1.9.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:48c7b5e6d2f3bf7917af301c275b05c5be3dd40bb04e80979c9e7a2ab31a00d1"}, - {file = "fastavro-1.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:05d13f98d4e325be40387e27da9bd60239968862fe12769258225c62ec906f04"}, - {file = "fastavro-1.9.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5b47948eb196263f6111bf34e1cd08d55529d4ed46eb50c1bc8c7c30a8d18868"}, - {file = "fastavro-1.9.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85b7a66ad521298ad9373dfe1897a6ccfc38feab54a47b97922e213ae5ad8870"}, - {file = "fastavro-1.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44cb154f863ad80e41aea72a709b12e1533b8728c89b9b1348af91a6154ab2f5"}, - {file = "fastavro-1.9.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b5f7f2b1fe21231fd01f1a2a90e714ae267fe633cd7ce930c0aea33d1c9f4901"}, - {file = "fastavro-1.9.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88fbbe16c61d90a89d78baeb5a34dc1c63a27b115adccdbd6b1fb6f787deacf2"}, - {file = "fastavro-1.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:753f5eedeb5ca86004e23a9ce9b41c5f25eb64a876f95edcc33558090a7f3e4b"}, - {file = "fastavro-1.9.5.tar.gz", hash = "sha256:6419ebf45f88132a9945c51fe555d4f10bb97c236288ed01894f957c6f914553"}, -] - -[package.extras] -codecs = ["cramjam", "lz4", "zstandard"] -lz4 = ["lz4"] -snappy = ["cramjam"] -zstandard = ["zstandard"] - -[[package]] -name = "filelock" -version = "3.15.4" -description = "A platform independent file lock." -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"}, - {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"}, -] - -[package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"] -typing = ["typing-extensions (>=4.8) ; python_version < \"3.11\""] - -[[package]] -name = "flatbuffers" -version = "24.3.25" -description = "The FlatBuffers serialization format for Python" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "flatbuffers-24.3.25-py2.py3-none-any.whl", hash = "sha256:8dbdec58f935f3765e4f7f3cf635ac3a77f83568138d6a2311f524ec96364812"}, - {file = "flatbuffers-24.3.25.tar.gz", hash = "sha256:de2ec5b203f21441716617f38443e0a8ebf3d25bf0d9c0bb0ce68fa00ad546a4"}, -] - -[[package]] -name = "frozenlist" -version = "1.4.1" -description = "A list-like structure which implements collections.abc.MutableSequence" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, - {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, - {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, - {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, - {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, - {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, - {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, - {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, - {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, - {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, - {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, - {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, - {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, -] - -[[package]] -name = "fsspec" -version = "2024.6.1" -description = "File-system specification" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "fsspec-2024.6.1-py3-none-any.whl", hash = "sha256:3cb443f8bcd2efb31295a5b9fdb02aee81d8452c80d28f97a6d0959e6cee101e"}, - {file = "fsspec-2024.6.1.tar.gz", hash = "sha256:fad7d7e209dd4c1208e3bbfda706620e0da5142bebbd9c384afb95b07e798e49"}, -] - -[package.extras] -abfs = ["adlfs"] -adl = ["adlfs"] -arrow = ["pyarrow (>=1)"] -dask = ["dask", "distributed"] -dev = ["pre-commit", "ruff"] -doc = ["numpydoc", "sphinx", "sphinx-design", "sphinx-rtd-theme", "yarl"] -dropbox = ["dropbox", "dropboxdrivefs", "requests"] -full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] -fuse = ["fusepy"] -gcs = ["gcsfs"] -git = ["pygit2"] -github = ["requests"] -gs = ["gcsfs"] -gui = ["panel"] -hdfs = ["pyarrow (>=1)"] -http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)"] -libarchive = ["libarchive-c"] -oci = ["ocifs"] -s3 = ["s3fs"] -sftp = ["paramiko"] -smb = ["smbprotocol"] -ssh = ["paramiko"] -test = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "numpy", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "requests"] -test-downstream = ["aiobotocore (>=2.5.4,<3.0.0)", "dask-expr", "dask[dataframe,test]", "moto[server] (>4,<5)", "pytest-timeout", "xarray"] -test-full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "cloudpickle", "dask", "distributed", "dropbox", "dropboxdrivefs", "fastparquet", "fusepy", "gcsfs", "jinja2", "kerchunk", "libarchive-c", "lz4", "notebook", "numpy", "ocifs", "pandas", "panel", "paramiko", "pyarrow", "pyarrow (>=1)", "pyftpdlib", "pygit2", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "python-snappy", "requests", "smbprotocol", "tqdm", "urllib3", "zarr", "zstandard"] -tqdm = ["tqdm"] - -[[package]] -name = "google-ai-generativelanguage" -version = "0.4.0" -description = "Google Ai Generativelanguage API client library" -optional = true -python-versions = ">=3.7" -groups = ["main"] -markers = "extra == \"google\"" -files = [ - {file = "google-ai-generativelanguage-0.4.0.tar.gz", hash = "sha256:c8199066c08f74c4e91290778329bb9f357ba1ea5d6f82de2bc0d10552bf4f8c"}, - {file = "google_ai_generativelanguage-0.4.0-py3-none-any.whl", hash = "sha256:e4c425376c1ee26c78acbc49a24f735f90ebfa81bf1a06495fae509a2433232c"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.34.0,<2.0.dev0 || >=2.11.dev0,<3.0.0.dev0", extras = ["grpc"]} -proto-plus = ">=1.22.3,<2.0.0.dev0" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" - -[[package]] -name = "google-api-core" -version = "2.19.1" -description = "Google API client core library" -optional = true -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google-api-core-2.19.1.tar.gz", hash = "sha256:f4695f1e3650b316a795108a76a1c416e6afb036199d1c1f1f110916df479ffd"}, - {file = "google_api_core-2.19.1-py3-none-any.whl", hash = "sha256:f12a9b8309b5e21d92483bbd47ce2c445861ec7d269ef6784ecc0ea8c1fa6125"}, -] - -[package.dependencies] -google-auth = ">=2.14.1,<3.0.dev0" -googleapis-common-protos = ">=1.56.2,<2.0.dev0" -grpcio = [ - {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, - {version = ">=1.33.2,<2.0.dev0", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, -] -grpcio-status = [ - {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, - {version = ">=1.33.2,<2.0.dev0", optional = true, markers = "extra == \"grpc\""}, -] -proto-plus = ">=1.22.3,<2.0.0.dev0" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" -requests = ">=2.18.0,<3.0.0.dev0" - -[package.extras] -grpc = ["grpcio (>=1.33.2,<2.0.dev0)", "grpcio (>=1.49.1,<2.0.dev0) ; python_version >= \"3.11\"", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0) ; python_version >= \"3.11\""] -grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] -grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] - -[[package]] -name = "google-api-python-client" -version = "2.137.0" -description = "Google API Client Library for Python" -optional = true -python-versions = ">=3.7" -groups = ["main"] -markers = "extra == \"gmail\" or extra == \"googledrive\"" -files = [ - {file = "google_api_python_client-2.137.0-py2.py3-none-any.whl", hash = "sha256:a8b5c5724885e5be9f5368739aa0ccf416627da4ebd914b410a090c18f84d692"}, - {file = "google_api_python_client-2.137.0.tar.gz", hash = "sha256:e739cb74aac8258b1886cb853b0722d47c81fe07ad649d7f2206f06530513c04"}, -] - -[package.dependencies] -google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0.dev0" -google-auth = ">=1.32.0,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0.dev0" -google-auth-httplib2 = ">=0.2.0,<1.0.0" -httplib2 = ">=0.19.0,<1.dev0" -uritemplate = ">=3.0.1,<5" - -[[package]] -name = "google-auth" -version = "2.32.0" -description = "Google Authentication Library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google_auth-2.32.0-py2.py3-none-any.whl", hash = "sha256:53326ea2ebec768070a94bee4e1b9194c9646ea0c2bd72422785bd0f9abfad7b"}, - {file = "google_auth-2.32.0.tar.gz", hash = "sha256:49315be72c55a6a37d62819e3573f6b416aca00721f7e3e31a008d928bf64022"}, -] - -[package.dependencies] -cachetools = ">=2.0.0,<6.0" -pyasn1-modules = ">=0.2.1" -rsa = ">=3.1.4,<5" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] -enterprise-cert = ["cryptography (==36.0.2)", "pyopenssl (==22.0.0)"] -pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] -reauth = ["pyu2f (>=0.1.5)"] -requests = ["requests (>=2.20.0,<3.0.0.dev0)"] - -[[package]] -name = "google-auth-httplib2" -version = "0.2.0" -description = "Google Authentication Library: httplib2 transport" -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"gmail\" or extra == \"googledrive\"" -files = [ - {file = "google-auth-httplib2-0.2.0.tar.gz", hash = "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05"}, - {file = "google_auth_httplib2-0.2.0-py2.py3-none-any.whl", hash = "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d"}, -] - -[package.dependencies] -google-auth = "*" -httplib2 = ">=0.19.0" - -[[package]] -name = "google-auth-oauthlib" -version = "1.2.1" -description = "Google Authentication Library" -optional = true -python-versions = ">=3.6" -groups = ["main"] -markers = "extra == \"gmail\" or extra == \"googledrive\"" -files = [ - {file = "google_auth_oauthlib-1.2.1-py2.py3-none-any.whl", hash = "sha256:2d58a27262d55aa1b87678c3ba7142a080098cbc2024f903c62355deb235d91f"}, - {file = "google_auth_oauthlib-1.2.1.tar.gz", hash = "sha256:afd0cad092a2eaa53cd8e8298557d6de1034c6cb4a740500b5357b648af97263"}, -] - -[package.dependencies] -google-auth = ">=2.15.0" -requests-oauthlib = ">=0.7.0" - -[package.extras] -tool = ["click (>=6.0.0)"] - -[[package]] -name = "google-cloud-aiplatform" -version = "1.59.0" -description = "Vertex AI API client library" -optional = true -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "google-cloud-aiplatform-1.59.0.tar.gz", hash = "sha256:2bebb59c0ba3e3b4b568305418ca1b021977988adbee8691a5bed09b037e7e63"}, - {file = "google_cloud_aiplatform-1.59.0-py2.py3-none-any.whl", hash = "sha256:549e6eb1844b0f853043309138ebe2db00de4bbd8197b3bde26804ac163ef52a"}, -] - -[package.dependencies] -docstring-parser = "<1" -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.8.dev0,<3.0.0.dev0", extras = ["grpc"]} -google-auth = ">=2.14.1,<3.0.0.dev0" -google-cloud-bigquery = ">=1.15.0,<3.20.0 || >3.20.0,<4.0.0.dev0" -google-cloud-resource-manager = ">=1.3.3,<3.0.0.dev0" -google-cloud-storage = ">=1.32.0,<3.0.0.dev0" -packaging = ">=14.3" -proto-plus = ">=1.22.3,<2.0.0.dev0" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" -pydantic = "<3" -shapely = "<3.0.0.dev0" - -[package.extras] -autologging = ["mlflow (>=1.27.0,<=2.1.1)"] -cloud-profiler = ["tensorboard-plugin-profile (>=2.4.0,<3.0.0.dev0)", "tensorflow (>=2.4.0,<3.0.0.dev0)", "werkzeug (>=2.0.0,<2.1.0.dev0)"] -datasets = ["pyarrow (>=10.0.1) ; python_version == \"3.11\"", "pyarrow (>=14.0.0) ; python_version >= \"3.12\"", "pyarrow (>=3.0.0,<8.0.dev0) ; python_version < \"3.11\""] -endpoint = ["requests (>=2.28.1)"] -full = ["cloudpickle (<3.0)", "docker (>=5.0.3)", "explainable-ai-sdk (>=1.0.0)", "fastapi (>=0.71.0,<=0.109.1)", "google-cloud-bigquery", "google-cloud-bigquery-storage", "google-cloud-logging (<4.0)", "google-vizier (>=0.1.6)", "httpx (>=0.23.0,<0.25.0)", "immutabledict", "lit-nlp (==0.4.0)", "mlflow (>=1.27.0,<=2.1.1)", "numpy (>=1.15.0)", "pandas (>=1.0.0)", "pandas (>=1.0.0,<2.2.0)", "pyarrow (>=10.0.1) ; python_version == \"3.11\"", "pyarrow (>=14.0.0) ; python_version >= \"3.12\"", "pyarrow (>=3.0.0,<8.0.dev0) ; python_version < \"3.11\"", "pyarrow (>=6.0.1)", "pydantic (<2)", "pyyaml (>=5.3.1,<7)", "ray[default] (>=2.4,<2.5.dev0 || >2.9.0,!=2.9.1,!=2.9.2,<=2.9.3) ; python_version < \"3.11\"", "ray[default] (>=2.5,<=2.9.3) ; python_version == \"3.11\"", "requests (>=2.28.1)", "setuptools (<70.0.0)", "starlette (>=0.17.1)", "tensorboard-plugin-profile (>=2.4.0,<3.0.0.dev0)", "tensorflow (>=2.3.0,<3.0.0.dev0)", "tensorflow (>=2.3.0,<3.0.0.dev0) ; python_version <= \"3.11\"", "tensorflow (>=2.4.0,<3.0.0.dev0)", "tqdm (>=4.23.0)", "urllib3 (>=1.21.1,<1.27)", "uvicorn[standard] (>=0.16.0)", "werkzeug (>=2.0.0,<2.1.0.dev0)"] -langchain = ["langchain (>=0.1.16,<0.3)", "langchain-core (<0.2)", "langchain-google-vertexai (<2)", "openinference-instrumentation-langchain (>=0.1.19,<0.2)", "tenacity (<=8.3)"] -langchain-testing = ["absl-py", "cloudpickle (>=3.0,<4.0)", "langchain (>=0.1.16,<0.3)", "langchain-core (<0.2)", "langchain-google-vertexai (<2)", "openinference-instrumentation-langchain (>=0.1.19,<0.2)", "opentelemetry-exporter-gcp-trace (<2)", "opentelemetry-sdk (<2)", "pydantic (>=2.6.3,<3)", "pytest-xdist", "tenacity (<=8.3)"] -lit = ["explainable-ai-sdk (>=1.0.0)", "lit-nlp (==0.4.0)", "pandas (>=1.0.0)", "tensorflow (>=2.3.0,<3.0.0.dev0)"] -metadata = ["numpy (>=1.15.0)", "pandas (>=1.0.0)"] -pipelines = ["pyyaml (>=5.3.1,<7)"] -prediction = ["docker (>=5.0.3)", "fastapi (>=0.71.0,<=0.109.1)", "httpx (>=0.23.0,<0.25.0)", "starlette (>=0.17.1)", "uvicorn[standard] (>=0.16.0)"] -preview = ["cloudpickle (<3.0)", "google-cloud-logging (<4.0)"] -private-endpoints = ["requests (>=2.28.1)", "urllib3 (>=1.21.1,<1.27)"] -rapid-evaluation = ["pandas (>=1.0.0,<2.2.0)", "tqdm (>=4.23.0)"] -ray = ["google-cloud-bigquery", "google-cloud-bigquery-storage", "immutabledict", "pandas (>=1.0.0,<2.2.0)", "pyarrow (>=6.0.1)", "pydantic (<2)", "ray[default] (>=2.4,<2.5.dev0 || >2.9.0,!=2.9.1,!=2.9.2,<=2.9.3) ; python_version < \"3.11\"", "ray[default] (>=2.5,<=2.9.3) ; python_version == \"3.11\"", "setuptools (<70.0.0)"] -ray-testing = ["google-cloud-bigquery", "google-cloud-bigquery-storage", "immutabledict", "pandas (>=1.0.0,<2.2.0)", "pyarrow (>=6.0.1)", "pydantic (<2)", "pytest-xdist", "ray[default] (>=2.4,<2.5.dev0 || >2.9.0,!=2.9.1,!=2.9.2,<=2.9.3) ; python_version < \"3.11\"", "ray[default] (>=2.5,<=2.9.3) ; python_version == \"3.11\"", "ray[train] (==2.9.3)", "scikit-learn", "setuptools (<70.0.0)", "tensorflow", "torch (>=2.0.0,<2.1.0)", "xgboost", "xgboost-ray"] -reasoningengine = ["cloudpickle (>=3.0,<4.0)", "opentelemetry-exporter-gcp-trace (<2)", "opentelemetry-sdk (<2)", "pydantic (>=2.6.3,<3)"] -tensorboard = ["tensorboard-plugin-profile (>=2.4.0,<3.0.0.dev0)", "tensorflow (>=2.3.0,<3.0.0.dev0) ; python_version <= \"3.11\"", "tensorflow (>=2.4.0,<3.0.0.dev0)", "werkzeug (>=2.0.0,<2.1.0.dev0)"] -testing = ["bigframes ; python_version >= \"3.10\"", "cloudpickle (<3.0)", "docker (>=5.0.3)", "explainable-ai-sdk (>=1.0.0)", "fastapi (>=0.71.0,<=0.109.1)", "google-api-core (>=2.11,<3.0.0)", "google-cloud-bigquery", "google-cloud-bigquery-storage", "google-cloud-logging (<4.0)", "google-vizier (>=0.1.6)", "grpcio-testing", "httpx (>=0.23.0,<0.25.0)", "immutabledict", "ipython", "kfp (>=2.6.0,<3.0.0)", "lit-nlp (==0.4.0)", "mlflow (>=1.27.0,<=2.1.1)", "nltk", "numpy (>=1.15.0)", "pandas (>=1.0.0)", "pandas (>=1.0.0,<2.2.0)", "pyarrow (>=10.0.1) ; python_version == \"3.11\"", "pyarrow (>=14.0.0) ; python_version >= \"3.12\"", "pyarrow (>=3.0.0,<8.0.dev0) ; python_version < \"3.11\"", "pyarrow (>=6.0.1)", "pydantic (<2)", "pyfakefs", "pytest-asyncio", "pytest-xdist", "pyyaml (>=5.3.1,<7)", "ray[default] (>=2.4,<2.5.dev0 || >2.9.0,!=2.9.1,!=2.9.2,<=2.9.3) ; python_version < \"3.11\"", "ray[default] (>=2.5,<=2.9.3) ; python_version == \"3.11\"", "requests (>=2.28.1)", "requests-toolbelt (<1.0.0)", "scikit-learn", "sentencepiece (>=0.2.0)", "setuptools (<70.0.0)", "starlette (>=0.17.1)", "tensorboard-plugin-profile (>=2.4.0,<3.0.0.dev0)", "tensorflow (==2.13.0) ; python_version <= \"3.11\"", "tensorflow (==2.16.1) ; python_version > \"3.11\"", "tensorflow (>=2.3.0,<3.0.0.dev0)", "tensorflow (>=2.3.0,<3.0.0.dev0) ; python_version <= \"3.11\"", "tensorflow (>=2.4.0,<3.0.0.dev0)", "torch (>=2.0.0,<2.1.0) ; python_version <= \"3.11\"", "torch (>=2.2.0) ; python_version > \"3.11\"", "tqdm (>=4.23.0)", "urllib3 (>=1.21.1,<1.27)", "uvicorn[standard] (>=0.16.0)", "werkzeug (>=2.0.0,<2.1.0.dev0)", "xgboost"] -tokenization = ["sentencepiece (>=0.2.0)"] -vizier = ["google-vizier (>=0.1.6)"] -xai = ["tensorflow (>=2.3.0,<3.0.0.dev0)"] - -[[package]] -name = "google-cloud-bigquery" -version = "3.25.0" -description = "Google BigQuery API client library" -optional = true -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google-cloud-bigquery-3.25.0.tar.gz", hash = "sha256:5b2aff3205a854481117436836ae1403f11f2594e6810a98886afd57eda28509"}, - {file = "google_cloud_bigquery-3.25.0-py2.py3-none-any.whl", hash = "sha256:7f0c371bc74d2a7fb74dacbc00ac0f90c8c2bec2289b51dd6685a275873b1ce9"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0.dev0", extras = ["grpc"]} -google-auth = ">=2.14.1,<3.0.0.dev0" -google-cloud-core = ">=1.6.0,<3.0.0.dev0" -google-resumable-media = ">=0.6.0,<3.0.dev0" -packaging = ">=20.0.0" -python-dateutil = ">=2.7.2,<3.0.dev0" -requests = ">=2.21.0,<3.0.0.dev0" - -[package.extras] -all = ["Shapely (>=1.8.4,<3.0.0.dev0)", "db-dtypes (>=0.3.0,<2.0.0.dev0)", "geopandas (>=0.9.0,<1.0.dev0)", "google-cloud-bigquery-storage (>=2.6.0,<3.0.0.dev0)", "grpcio (>=1.47.0,<2.0.dev0)", "grpcio (>=1.49.1,<2.0.dev0) ; python_version >= \"3.11\"", "importlib-metadata (>=1.0.0) ; python_version < \"3.8\"", "ipykernel (>=6.0.0)", "ipython (>=7.23.1,!=8.1.0)", "ipywidgets (>=7.7.0)", "opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)", "pandas (>=1.1.0)", "proto-plus (>=1.15.0,<2.0.0.dev0)", "protobuf (>=3.19.5,!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0.dev0)", "pyarrow (>=3.0.0)", "tqdm (>=4.7.4,<5.0.0.dev0)"] -bigquery-v2 = ["proto-plus (>=1.15.0,<2.0.0.dev0)", "protobuf (>=3.19.5,!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0.dev0)"] -bqstorage = ["google-cloud-bigquery-storage (>=2.6.0,<3.0.0.dev0)", "grpcio (>=1.47.0,<2.0.dev0)", "grpcio (>=1.49.1,<2.0.dev0) ; python_version >= \"3.11\"", "pyarrow (>=3.0.0)"] -geopandas = ["Shapely (>=1.8.4,<3.0.0.dev0)", "geopandas (>=0.9.0,<1.0.dev0)"] -ipython = ["ipykernel (>=6.0.0)", "ipython (>=7.23.1,!=8.1.0)"] -ipywidgets = ["ipykernel (>=6.0.0)", "ipywidgets (>=7.7.0)"] -opentelemetry = ["opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)"] -pandas = ["db-dtypes (>=0.3.0,<2.0.0.dev0)", "importlib-metadata (>=1.0.0) ; python_version < \"3.8\"", "pandas (>=1.1.0)", "pyarrow (>=3.0.0)"] -tqdm = ["tqdm (>=4.7.4,<5.0.0.dev0)"] - -[[package]] -name = "google-cloud-core" -version = "2.4.1" -description = "Google Cloud API client core library" -optional = true -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google-cloud-core-2.4.1.tar.gz", hash = "sha256:9b7749272a812bde58fff28868d0c5e2f585b82f37e09a1f6ed2d4d10f134073"}, - {file = "google_cloud_core-2.4.1-py2.py3-none-any.whl", hash = "sha256:a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61"}, -] - -[package.dependencies] -google-api-core = ">=1.31.6,<2.0.dev0 || >2.3.0,<3.0.0.dev0" -google-auth = ">=1.25.0,<3.0.dev0" - -[package.extras] -grpc = ["grpcio (>=1.38.0,<2.0.dev0)", "grpcio-status (>=1.38.0,<2.0.dev0)"] - -[[package]] -name = "google-cloud-resource-manager" -version = "1.12.4" -description = "Google Cloud Resource Manager API client library" -optional = true -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google-cloud-resource-manager-1.12.4.tar.gz", hash = "sha256:3eda914a925e92465ef80faaab7e0f7a9312d486dd4e123d2c76e04bac688ff0"}, - {file = "google_cloud_resource_manager-1.12.4-py2.py3-none-any.whl", hash = "sha256:0b6663585f7f862166c0fb4c55fdda721fce4dc2dc1d5b52d03ee4bf2653a85f"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0.dev0", extras = ["grpc"]} -google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0.dev0" -grpc-google-iam-v1 = ">=0.12.4,<1.0.0.dev0" -proto-plus = ">=1.22.3,<2.0.0.dev0" -protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" - -[[package]] -name = "google-cloud-storage" -version = "2.17.0" -description = "Google Cloud Storage API client library" -optional = true -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google-cloud-storage-2.17.0.tar.gz", hash = "sha256:49378abff54ef656b52dca5ef0f2eba9aa83dc2b2c72c78714b03a1a95fe9388"}, - {file = "google_cloud_storage-2.17.0-py2.py3-none-any.whl", hash = "sha256:5b393bc766b7a3bc6f5407b9e665b2450d36282614b7945e570b3480a456d1e1"}, -] - -[package.dependencies] -google-api-core = ">=2.15.0,<3.0.0.dev0" -google-auth = ">=2.26.1,<3.0.dev0" -google-cloud-core = ">=2.3.0,<3.0.dev0" -google-crc32c = ">=1.0,<2.0.dev0" -google-resumable-media = ">=2.6.0" -requests = ">=2.18.0,<3.0.0.dev0" - -[package.extras] -protobuf = ["protobuf (<5.0.0.dev0)"] - -[[package]] -name = "google-crc32c" -version = "1.5.0" -description = "A python wrapper of the C library 'Google CRC32C'" -optional = true -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google-crc32c-1.5.0.tar.gz", hash = "sha256:89284716bc6a5a415d4eaa11b1726d2d60a0cd12aadf5439828353662ede9dd7"}, - {file = "google_crc32c-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:596d1f98fc70232fcb6590c439f43b350cb762fb5d61ce7b0e9db4539654cc13"}, - {file = "google_crc32c-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:be82c3c8cfb15b30f36768797a640e800513793d6ae1724aaaafe5bf86f8f346"}, - {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:461665ff58895f508e2866824a47bdee72497b091c730071f2b7575d5762ab65"}, - {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2096eddb4e7c7bdae4bd69ad364e55e07b8316653234a56552d9c988bd2d61b"}, - {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:116a7c3c616dd14a3de8c64a965828b197e5f2d121fedd2f8c5585c547e87b02"}, - {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5829b792bf5822fd0a6f6eb34c5f81dd074f01d570ed7f36aa101d6fc7a0a6e4"}, - {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:64e52e2b3970bd891309c113b54cf0e4384762c934d5ae56e283f9a0afcd953e"}, - {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:02ebb8bf46c13e36998aeaad1de9b48f4caf545e91d14041270d9dca767b780c"}, - {file = "google_crc32c-1.5.0-cp310-cp310-win32.whl", hash = "sha256:2e920d506ec85eb4ba50cd4228c2bec05642894d4c73c59b3a2fe20346bd00ee"}, - {file = "google_crc32c-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:07eb3c611ce363c51a933bf6bd7f8e3878a51d124acfc89452a75120bc436289"}, - {file = "google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273"}, - {file = "google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298"}, - {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57"}, - {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8485b340a6a9e76c62a7dce3c98e5f102c9219f4cfbf896a00cf48caf078d438"}, - {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906"}, - {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f583edb943cf2e09c60441b910d6a20b4d9d626c75a36c8fcac01a6c96c01183"}, - {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:a1fd716e7a01f8e717490fbe2e431d2905ab8aa598b9b12f8d10abebb36b04dd"}, - {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:72218785ce41b9cfd2fc1d6a017dc1ff7acfc4c17d01053265c41a2c0cc39b8c"}, - {file = "google_crc32c-1.5.0-cp311-cp311-win32.whl", hash = "sha256:66741ef4ee08ea0b2cc3c86916ab66b6aef03768525627fd6a1b34968b4e3709"}, - {file = "google_crc32c-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:98cb4d057f285bd80d8778ebc4fde6b4d509ac3f331758fb1528b733215443ae"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd8536e902db7e365f49e7d9029283403974ccf29b13fc7028b97e2295b33556"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19e0a019d2c4dcc5e598cd4a4bc7b008546b0358bd322537c74ad47a5386884f"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02c65b9817512edc6a4ae7c7e987fea799d2e0ee40c53ec573a692bee24de876"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6ac08d24c1f16bd2bf5eca8eaf8304812f44af5cfe5062006ec676e7e1d50afc"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3359fc442a743e870f4588fcf5dcbc1bf929df1fad8fb9905cd94e5edb02e84c"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e986b206dae4476f41bcec1faa057851f3889503a70e1bdb2378d406223994a"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:de06adc872bcd8c2a4e0dc51250e9e65ef2ca91be023b9d13ebd67c2ba552e1e"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-win32.whl", hash = "sha256:d3515f198eaa2f0ed49f8819d5732d70698c3fa37384146079b3799b97667a94"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:67b741654b851abafb7bc625b6d1cdd520a379074e64b6a128e3b688c3c04740"}, - {file = "google_crc32c-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c02ec1c5856179f171e032a31d6f8bf84e5a75c45c33b2e20a3de353b266ebd8"}, - {file = "google_crc32c-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:edfedb64740750e1a3b16152620220f51d58ff1b4abceb339ca92e934775c27a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84e6e8cd997930fc66d5bb4fde61e2b62ba19d62b7abd7a69920406f9ecca946"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:024894d9d3cfbc5943f8f230e23950cd4906b2fe004c72e29b209420a1e6b05a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:998679bf62b7fb599d2878aa3ed06b9ce688b8974893e7223c60db155f26bd8d"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:83c681c526a3439b5cf94f7420471705bbf96262f49a6fe546a6db5f687a3d4a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4c6fdd4fccbec90cc8a01fc00773fcd5fa28db683c116ee3cb35cd5da9ef6c37"}, - {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5ae44e10a8e3407dbe138984f21e536583f2bba1be9491239f942c2464ac0894"}, - {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37933ec6e693e51a5b07505bd05de57eee12f3e8c32b07da7e73669398e6630a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-win32.whl", hash = "sha256:fe70e325aa68fa4b5edf7d1a4b6f691eb04bbccac0ace68e34820d283b5f80d4"}, - {file = "google_crc32c-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:74dea7751d98034887dbd821b7aae3e1d36eda111d6ca36c206c44478035709c"}, - {file = "google_crc32c-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c6c777a480337ac14f38564ac88ae82d4cd238bf293f0a22295b66eb89ffced7"}, - {file = "google_crc32c-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:759ce4851a4bb15ecabae28f4d2e18983c244eddd767f560165563bf9aefbc8d"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f13cae8cc389a440def0c8c52057f37359014ccbc9dc1f0827936bcd367c6100"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e560628513ed34759456a416bf86b54b2476c59144a9138165c9a1575801d0d9"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1674e4307fa3024fc897ca774e9c7562c957af85df55efe2988ed9056dc4e57"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:278d2ed7c16cfc075c91378c4f47924c0625f5fc84b2d50d921b18b7975bd210"}, - {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d5280312b9af0976231f9e317c20e4a61cd2f9629b7bfea6a693d1878a264ebd"}, - {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8b87e1a59c38f275c0e3676fc2ab6d59eccecfd460be267ac360cc31f7bcde96"}, - {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7c074fece789b5034b9b1404a1f8208fc2d4c6ce9decdd16e8220c5a793e6f61"}, - {file = "google_crc32c-1.5.0-cp39-cp39-win32.whl", hash = "sha256:7f57f14606cd1dd0f0de396e1e53824c371e9544a822648cd76c034d209b559c"}, - {file = "google_crc32c-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:a2355cba1f4ad8b6988a4ca3feed5bff33f6af2d7f134852cf279c2aebfde541"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f314013e7dcd5cf45ab1945d92e713eec788166262ae8deb2cfacd53def27325"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b747a674c20a67343cb61d43fdd9207ce5da6a99f629c6e2541aa0e89215bcd"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8f24ed114432de109aa9fd317278518a5af2d31ac2ea6b952b2f7782b43da091"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8667b48e7a7ef66afba2c81e1094ef526388d35b873966d8a9a447974ed9178"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:1c7abdac90433b09bad6c43a43af253e688c9cfc1c86d332aed13f9a7c7f65e2"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6f998db4e71b645350b9ac28a2167e6632c239963ca9da411523bb439c5c514d"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c99616c853bb585301df6de07ca2cadad344fd1ada6d62bb30aec05219c45d2"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ad40e31093a4af319dadf503b2467ccdc8f67c72e4bcba97f8c10cb078207b5"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd67cf24a553339d5062eff51013780a00d6f97a39ca062781d06b3a73b15462"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:398af5e3ba9cf768787eef45c803ff9614cc3e22a5b2f7d7ae116df8b11e3314"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b1f8133c9a275df5613a451e73f36c2aea4fe13c5c8997e22cf355ebd7bd0728"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ba053c5f50430a3fcfd36f75aff9caeba0440b2d076afdb79a318d6ca245f88"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:272d3892a1e1a2dbc39cc5cde96834c236d5327e2122d3aaa19f6614531bb6eb"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:635f5d4dd18758a1fbd1049a8e8d2fee4ffed124462d837d1a02a0e009c3ab31"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c672d99a345849301784604bfeaeba4db0c7aae50b95be04dd651fd2a7310b93"}, -] - -[package.extras] -testing = ["pytest"] - -[[package]] -name = "google-generativeai" -version = "0.3.2" -description = "Google Generative AI High level API client library and tools." -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"google\"" -files = [ - {file = "google_generativeai-0.3.2-py3-none-any.whl", hash = "sha256:8761147e6e167141932dc14a7b7af08f2310dd56668a78d206c19bb8bd85bcd7"}, -] - -[package.dependencies] -google-ai-generativelanguage = "0.4.0" -google-api-core = "*" -google-auth = "*" -protobuf = "*" -tqdm = "*" -typing-extensions = "*" - -[package.extras] -dev = ["Pillow", "absl-py", "black", "ipython", "nose2", "pandas", "pytype", "pyyaml"] - -[[package]] -name = "google-resumable-media" -version = "2.7.1" -description = "Utilities for Google Media Downloads and Resumable Uploads" -optional = true -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google-resumable-media-2.7.1.tar.gz", hash = "sha256:eae451a7b2e2cdbaaa0fd2eb00cc8a1ee5e95e16b55597359cbc3d27d7d90e33"}, - {file = "google_resumable_media-2.7.1-py2.py3-none-any.whl", hash = "sha256:103ebc4ba331ab1bfdac0250f8033627a2cd7cde09e7ccff9181e31ba4315b2c"}, -] - -[package.dependencies] -google-crc32c = ">=1.0,<2.0.dev0" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "google-auth (>=1.22.0,<2.0.dev0)"] -requests = ["requests (>=2.18.0,<3.0.0.dev0)"] - -[[package]] -name = "googleapis-common-protos" -version = "1.63.2" -description = "Common protobufs used in Google APIs" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "googleapis-common-protos-1.63.2.tar.gz", hash = "sha256:27c5abdffc4911f28101e635de1533fb4cfd2c37fbaa9174587c799fac90aa87"}, - {file = "googleapis_common_protos-1.63.2-py2.py3-none-any.whl", hash = "sha256:27a2499c7e8aff199665b22741997e485eccc8645aa9176c7c988e6fae507945"}, -] - -[package.dependencies] -grpcio = {version = ">=1.44.0,<2.0.0.dev0", optional = true, markers = "extra == \"grpc\""} -protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" - -[package.extras] -grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] - -[[package]] -name = "gpt4all" -version = "2.0.2" -description = "Python bindings for GPT4All" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"opensource\"" -files = [ - {file = "gpt4all-2.0.2-py3-none-macosx_10_15_universal2.whl", hash = "sha256:f18f348d21e2ce8e45dbf8334960670660b53f69a8e47a26bb7e64924e6ed130"}, - {file = "gpt4all-2.0.2-py3-none-manylinux1_x86_64.whl", hash = "sha256:e4c19df94f45829565563017577b299c012ebed18ebea1d6df0273ef89c92a01"}, - {file = "gpt4all-2.0.2-py3-none-win_amd64.whl", hash = "sha256:c09440bfb3463b9e278875fc726cf1f75d2a2b19bb73d97dde5e57b0b1f6e059"}, -] - -[package.dependencies] -requests = "*" -tqdm = "*" - -[package.extras] -dev = ["black", "isort", "mkautodoc", "mkdocs-jupyter", "mkdocs-material", "mkdocstrings[python]", "pytest", "setuptools", "twine", "wheel"] - -[[package]] -name = "gptcache" -version = "0.1.43" -description = "GPTCache, a powerful caching library that can be used to speed up and lower the cost of chat applications that rely on the LLM service. GPTCache works as a memcache for AIGC applications, similar to how Redis works for traditional applications." -optional = false -python-versions = ">=3.8.1" -groups = ["main"] -files = [ - {file = "gptcache-0.1.43-py3-none-any.whl", hash = "sha256:9c557ec9cc14428942a0ebf1c838520dc6d2be801d67bb6964807043fc2feaf5"}, - {file = "gptcache-0.1.43.tar.gz", hash = "sha256:cebe7ec5e32a3347bf839e933a34e67c7fcae620deaa7cb8c6d7d276c8686f1a"}, -] - -[package.dependencies] -cachetools = "*" -numpy = "*" -requests = "*" - -[[package]] -name = "greenlet" -version = "3.0.3" -description = "Lightweight in-process concurrent programming" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "(platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\") and python_version < \"3.13\"" -files = [ - {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405"}, - {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f"}, - {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb"}, - {file = "greenlet-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9"}, - {file = "greenlet-3.0.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22"}, - {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3"}, - {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d"}, - {file = "greenlet-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728"}, - {file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf"}, - {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305"}, - {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6"}, - {file = "greenlet-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2"}, - {file = "greenlet-3.0.3-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41"}, - {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7"}, - {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6"}, - {file = "greenlet-3.0.3-cp37-cp37m-win32.whl", hash = "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d"}, - {file = "greenlet-3.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67"}, - {file = "greenlet-3.0.3-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4"}, - {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5"}, - {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da"}, - {file = "greenlet-3.0.3-cp38-cp38-win32.whl", hash = "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3"}, - {file = "greenlet-3.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf"}, - {file = "greenlet-3.0.3-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b"}, - {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6"}, - {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113"}, - {file = "greenlet-3.0.3-cp39-cp39-win32.whl", hash = "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e"}, - {file = "greenlet-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067"}, - {file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"}, -] - -[package.extras] -docs = ["Sphinx", "furo"] -test = ["objgraph", "psutil"] - -[[package]] -name = "grpc-google-iam-v1" -version = "0.13.1" -description = "IAM API client library" -optional = true -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "grpc-google-iam-v1-0.13.1.tar.gz", hash = "sha256:3ff4b2fd9d990965e410965253c0da6f66205d5a8291c4c31c6ebecca18a9001"}, - {file = "grpc_google_iam_v1-0.13.1-py2.py3-none-any.whl", hash = "sha256:c3e86151a981811f30d5e7330f271cee53e73bb87755e88cc3b6f0c7b5fe374e"}, -] - -[package.dependencies] -googleapis-common-protos = {version = ">=1.56.0,<2.0.0.dev0", extras = ["grpc"]} -grpcio = ">=1.44.0,<2.0.0.dev0" -protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" - -[[package]] -name = "grpcio" -version = "1.63.0" -description = "HTTP/2-based RPC framework" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "grpcio-1.63.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:2e93aca840c29d4ab5db93f94ed0a0ca899e241f2e8aec6334ab3575dc46125c"}, - {file = "grpcio-1.63.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:91b73d3f1340fefa1e1716c8c1ec9930c676d6b10a3513ab6c26004cb02d8b3f"}, - {file = "grpcio-1.63.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:b3afbd9d6827fa6f475a4f91db55e441113f6d3eb9b7ebb8fb806e5bb6d6bd0d"}, - {file = "grpcio-1.63.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8f3f6883ce54a7a5f47db43289a0a4c776487912de1a0e2cc83fdaec9685cc9f"}, - {file = "grpcio-1.63.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf8dae9cc0412cb86c8de5a8f3be395c5119a370f3ce2e69c8b7d46bb9872c8d"}, - {file = "grpcio-1.63.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:08e1559fd3b3b4468486b26b0af64a3904a8dbc78d8d936af9c1cf9636eb3e8b"}, - {file = "grpcio-1.63.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5c039ef01516039fa39da8a8a43a95b64e288f79f42a17e6c2904a02a319b357"}, - {file = "grpcio-1.63.0-cp310-cp310-win32.whl", hash = "sha256:ad2ac8903b2eae071055a927ef74121ed52d69468e91d9bcbd028bd0e554be6d"}, - {file = "grpcio-1.63.0-cp310-cp310-win_amd64.whl", hash = "sha256:b2e44f59316716532a993ca2966636df6fbe7be4ab6f099de6815570ebe4383a"}, - {file = "grpcio-1.63.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:f28f8b2db7b86c77916829d64ab21ff49a9d8289ea1564a2b2a3a8ed9ffcccd3"}, - {file = "grpcio-1.63.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:65bf975639a1f93bee63ca60d2e4951f1b543f498d581869922910a476ead2f5"}, - {file = "grpcio-1.63.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:b5194775fec7dc3dbd6a935102bb156cd2c35efe1685b0a46c67b927c74f0cfb"}, - {file = "grpcio-1.63.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4cbb2100ee46d024c45920d16e888ee5d3cf47c66e316210bc236d5bebc42b3"}, - {file = "grpcio-1.63.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ff737cf29b5b801619f10e59b581869e32f400159e8b12d7a97e7e3bdeee6a2"}, - {file = "grpcio-1.63.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cd1e68776262dd44dedd7381b1a0ad09d9930ffb405f737d64f505eb7f77d6c7"}, - {file = "grpcio-1.63.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:93f45f27f516548e23e4ec3fbab21b060416007dbe768a111fc4611464cc773f"}, - {file = "grpcio-1.63.0-cp311-cp311-win32.whl", hash = "sha256:878b1d88d0137df60e6b09b74cdb73db123f9579232c8456f53e9abc4f62eb3c"}, - {file = "grpcio-1.63.0-cp311-cp311-win_amd64.whl", hash = "sha256:756fed02dacd24e8f488f295a913f250b56b98fb793f41d5b2de6c44fb762434"}, - {file = "grpcio-1.63.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:93a46794cc96c3a674cdfb59ef9ce84d46185fe9421baf2268ccb556f8f81f57"}, - {file = "grpcio-1.63.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a7b19dfc74d0be7032ca1eda0ed545e582ee46cd65c162f9e9fc6b26ef827dc6"}, - {file = "grpcio-1.63.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:8064d986d3a64ba21e498b9a376cbc5d6ab2e8ab0e288d39f266f0fca169b90d"}, - {file = "grpcio-1.63.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:219bb1848cd2c90348c79ed0a6b0ea51866bc7e72fa6e205e459fedab5770172"}, - {file = "grpcio-1.63.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2d60cd1d58817bc5985fae6168d8b5655c4981d448d0f5b6194bbcc038090d2"}, - {file = "grpcio-1.63.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9e350cb096e5c67832e9b6e018cf8a0d2a53b2a958f6251615173165269a91b0"}, - {file = "grpcio-1.63.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:56cdf96ff82e3cc90dbe8bac260352993f23e8e256e063c327b6cf9c88daf7a9"}, - {file = "grpcio-1.63.0-cp312-cp312-win32.whl", hash = "sha256:3a6d1f9ea965e750db7b4ee6f9fdef5fdf135abe8a249e75d84b0a3e0c668a1b"}, - {file = "grpcio-1.63.0-cp312-cp312-win_amd64.whl", hash = "sha256:d2497769895bb03efe3187fb1888fc20e98a5f18b3d14b606167dacda5789434"}, - {file = "grpcio-1.63.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:fdf348ae69c6ff484402cfdb14e18c1b0054ac2420079d575c53a60b9b2853ae"}, - {file = "grpcio-1.63.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a3abfe0b0f6798dedd2e9e92e881d9acd0fdb62ae27dcbbfa7654a57e24060c0"}, - {file = "grpcio-1.63.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:6ef0ad92873672a2a3767cb827b64741c363ebaa27e7f21659e4e31f4d750280"}, - {file = "grpcio-1.63.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b416252ac5588d9dfb8a30a191451adbf534e9ce5f56bb02cd193f12d8845b7f"}, - {file = "grpcio-1.63.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3b77eaefc74d7eb861d3ffbdf91b50a1bb1639514ebe764c47773b833fa2d91"}, - {file = "grpcio-1.63.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b005292369d9c1f80bf70c1db1c17c6c342da7576f1c689e8eee4fb0c256af85"}, - {file = "grpcio-1.63.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cdcda1156dcc41e042d1e899ba1f5c2e9f3cd7625b3d6ebfa619806a4c1aadda"}, - {file = "grpcio-1.63.0-cp38-cp38-win32.whl", hash = "sha256:01799e8649f9e94ba7db1aeb3452188048b0019dc37696b0f5ce212c87c560c3"}, - {file = "grpcio-1.63.0-cp38-cp38-win_amd64.whl", hash = "sha256:6a1a3642d76f887aa4009d92f71eb37809abceb3b7b5a1eec9c554a246f20e3a"}, - {file = "grpcio-1.63.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:75f701ff645858a2b16bc8c9fc68af215a8bb2d5a9b647448129de6e85d52bce"}, - {file = "grpcio-1.63.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cacdef0348a08e475a721967f48206a2254a1b26ee7637638d9e081761a5ba86"}, - {file = "grpcio-1.63.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:0697563d1d84d6985e40ec5ec596ff41b52abb3fd91ec240e8cb44a63b895094"}, - {file = "grpcio-1.63.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6426e1fb92d006e47476d42b8f240c1d916a6d4423c5258ccc5b105e43438f61"}, - {file = "grpcio-1.63.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e48cee31bc5f5a31fb2f3b573764bd563aaa5472342860edcc7039525b53e46a"}, - {file = "grpcio-1.63.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:50344663068041b34a992c19c600236e7abb42d6ec32567916b87b4c8b8833b3"}, - {file = "grpcio-1.63.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:259e11932230d70ef24a21b9fb5bb947eb4703f57865a404054400ee92f42f5d"}, - {file = "grpcio-1.63.0-cp39-cp39-win32.whl", hash = "sha256:a44624aad77bf8ca198c55af811fd28f2b3eaf0a50ec5b57b06c034416ef2d0a"}, - {file = "grpcio-1.63.0-cp39-cp39-win_amd64.whl", hash = "sha256:166e5c460e5d7d4656ff9e63b13e1f6029b122104c1633d5f37eaea348d7356d"}, - {file = "grpcio-1.63.0.tar.gz", hash = "sha256:f3023e14805c61bc439fb40ca545ac3d5740ce66120a678a3c6c2c55b70343d1"}, -] - -[package.extras] -protobuf = ["grpcio-tools (>=1.63.0)"] - -[[package]] -name = "grpcio-status" -version = "1.62.2" -description = "Status proto mapping for gRPC" -optional = true -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "grpcio-status-1.62.2.tar.gz", hash = "sha256:62e1bfcb02025a1cd73732a2d33672d3e9d0df4d21c12c51e0bbcaf09bab742a"}, - {file = "grpcio_status-1.62.2-py3-none-any.whl", hash = "sha256:206ddf0eb36bc99b033f03b2c8e95d319f0044defae9b41ae21408e7e0cda48f"}, -] - -[package.dependencies] -googleapis-common-protos = ">=1.5.5" -grpcio = ">=1.62.2" -protobuf = ">=4.21.6" - -[[package]] -name = "grpcio-tools" -version = "1.62.2" -description = "Protobuf code generator for gRPC" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "grpcio-tools-1.62.2.tar.gz", hash = "sha256:5fd5e1582b678e6b941ee5f5809340be5e0724691df5299aae8226640f94e18f"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-linux_armv7l.whl", hash = "sha256:1679b4903aed2dc5bd8cb22a452225b05dc8470a076f14fd703581efc0740cdb"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:9d41e0e47dd075c075bb8f103422968a65dd0d8dc8613288f573ae91eb1053ba"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:987e774f74296842bbffd55ea8826370f70c499e5b5f71a8cf3103838b6ee9c3"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40cd4eeea4b25bcb6903b82930d579027d034ba944393c4751cdefd9c49e6989"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6746bc823958499a3cf8963cc1de00072962fb5e629f26d658882d3f4c35095"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2ed775e844566ce9ce089be9a81a8b928623b8ee5820f5e4d58c1a9d33dfc5ae"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bdc5dd3f57b5368d5d661d5d3703bcaa38bceca59d25955dff66244dbc987271"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-win32.whl", hash = "sha256:3a8d6f07e64c0c7756f4e0c4781d9d5a2b9cc9cbd28f7032a6fb8d4f847d0445"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-win_amd64.whl", hash = "sha256:e33b59fb3efdddeb97ded988a871710033e8638534c826567738d3edce528752"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-linux_armv7l.whl", hash = "sha256:472505d030135d73afe4143b0873efe0dcb385bd6d847553b4f3afe07679af00"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:ec674b4440ef4311ac1245a709e87b36aca493ddc6850eebe0b278d1f2b6e7d1"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:184b4174d4bd82089d706e8223e46c42390a6ebac191073b9772abc77308f9fa"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c195d74fe98541178ece7a50dad2197d43991e0f77372b9a88da438be2486f12"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a34d97c62e61bfe9e6cff0410fe144ac8cca2fc979ad0be46b7edf026339d161"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cbb8453ae83a1db2452b7fe0f4b78e4a8dd32be0f2b2b73591ae620d4d784d3d"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4f989e5cebead3ae92c6abf6bf7b19949e1563a776aea896ac5933f143f0c45d"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-win32.whl", hash = "sha256:c48fabe40b9170f4e3d7dd2c252e4f1ff395dc24e49ac15fc724b1b6f11724da"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-win_amd64.whl", hash = "sha256:8c616d0ad872e3780693fce6a3ac8ef00fc0963e6d7815ce9dcfae68ba0fc287"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-linux_armv7l.whl", hash = "sha256:10cc3321704ecd17c93cf68c99c35467a8a97ffaaed53207e9b2da6ae0308ee1"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:9be84ff6d47fd61462be7523b49d7ba01adf67ce4e1447eae37721ab32464dd8"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:d82f681c9a9d933a9d8068e8e382977768e7779ddb8870fa0cf918d8250d1532"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:04c607029ae3660fb1624ed273811ffe09d57d84287d37e63b5b802a35897329"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72b61332f1b439c14cbd3815174a8f1d35067a02047c32decd406b3a09bb9890"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8214820990d01b52845f9fbcb92d2b7384a0c321b303e3ac614c219dc7d1d3af"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:462e0ab8dd7c7b70bfd6e3195eebc177549ede5cf3189814850c76f9a340d7ce"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-win32.whl", hash = "sha256:fa107460c842e4c1a6266150881694fefd4f33baa544ea9489601810c2210ef8"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-win_amd64.whl", hash = "sha256:759c60f24c33a181bbbc1232a6752f9b49fbb1583312a4917e2b389fea0fb0f2"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-linux_armv7l.whl", hash = "sha256:45db5da2bcfa88f2b86b57ef35daaae85c60bd6754a051d35d9449c959925b57"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:ab84bae88597133f6ea7a2bdc57b2fda98a266fe8d8d4763652cbefd20e73ad7"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:7a49bccae1c7d154b78e991885c3111c9ad8c8fa98e91233de425718f47c6139"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7e439476b29d6dac363b321781a113794397afceeb97dad85349db5f1cb5e9a"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ea369c4d1567d1acdf69c8ea74144f4ccad9e545df7f9a4fc64c94fa7684ba3"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f955702dc4b530696375251319d05223b729ed24e8673c2129f7a75d2caefbb"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3708a747aa4b6b505727282ca887041174e146ae030ebcadaf4c1d346858df62"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-win_amd64.whl", hash = "sha256:2ce149ea55eadb486a7fb75a20f63ef3ac065ee6a0240ed25f3549ce7954c653"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-linux_armv7l.whl", hash = "sha256:58cbb24b3fa6ae35aa9c210fcea3a51aa5fef0cd25618eb4fd94f746d5a9b703"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:6413581e14a80e0b4532577766cf0586de4dd33766a31b3eb5374a746771c07d"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:47117c8a7e861382470d0e22d336e5a91fdc5f851d1db44fa784b9acea190d87"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f1ba79a253df9e553d20319c615fa2b429684580fa042dba618d7f6649ac7e4"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04a394cf5e51ba9be412eb9f6c482b6270bd81016e033e8eb7d21b8cc28fe8b5"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3c53b221378b035ae2f1881cbc3aca42a6075a8e90e1a342c2f205eb1d1aa6a1"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c384c838b34d1b67068e51b5bbe49caa6aa3633acd158f1ab16b5da8d226bc53"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-win32.whl", hash = "sha256:19ea69e41c3565932aa28a202d1875ec56786aea46a2eab54a3b28e8a27f9517"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-win_amd64.whl", hash = "sha256:1d768a5c07279a4c461ebf52d0cec1c6ca85c6291c71ec2703fe3c3e7e28e8c4"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-linux_armv7l.whl", hash = "sha256:5b07b5874187e170edfbd7aa2ca3a54ebf3b2952487653e8c0b0d83601c33035"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:d58389fe8be206ddfb4fa703db1e24c956856fcb9a81da62b13577b3a8f7fda7"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:7d8b4e00c3d7237b92260fc18a561cd81f1da82e8be100db1b7d816250defc66"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fe08d2038f2b7c53259b5c49e0ad08c8e0ce2b548d8185993e7ef67e8592cca"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19216e1fb26dbe23d12a810517e1b3fbb8d4f98b1a3fbebeec9d93a79f092de4"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b8574469ecc4ff41d6bb95f44e0297cdb0d95bade388552a9a444db9cd7485cd"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4f6f32d39283ea834a493fccf0ebe9cfddee7577bdcc27736ad4be1732a36399"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-win32.whl", hash = "sha256:76eb459bdf3fb666e01883270beee18f3f11ed44488486b61cd210b4e0e17cc1"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-win_amd64.whl", hash = "sha256:217c2ee6a7ce519a55958b8622e21804f6fdb774db08c322f4c9536c35fdce7c"}, -] - -[package.dependencies] -grpcio = ">=1.62.2" -protobuf = ">=4.21.6,<5.0.dev0" -setuptools = "*" - -[[package]] -name = "h11" -version = "0.16.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, - {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, -] - -[[package]] -name = "h2" -version = "4.1.0" -description = "HTTP/2 State-Machine based protocol implementation" -optional = false -python-versions = ">=3.6.1" -groups = ["main"] -files = [ - {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, - {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, -] - -[package.dependencies] -hpack = ">=4.0,<5" -hyperframe = ">=6.0,<7" - -[[package]] -name = "hpack" -version = "4.0.0" -description = "Pure-Python HPACK header compression" -optional = false -python-versions = ">=3.6.1" -groups = ["main"] -files = [ - {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, - {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, -] - -[[package]] -name = "httpcore" -version = "1.0.9" -description = "A minimal low-level HTTP client." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, - {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, -] - -[package.dependencies] -certifi = "*" -h11 = ">=0.16" - -[package.extras] -asyncio = ["anyio (>=4.0,<5.0)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<1.0)"] - -[[package]] -name = "httplib2" -version = "0.22.0" -description = "A comprehensive HTTP client library." -optional = true -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -markers = "extra == \"gmail\" or extra == \"googledrive\"" -files = [ - {file = "httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc"}, - {file = "httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"}, -] - -[package.dependencies] -pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} - -[[package]] -name = "httptools" -version = "0.6.1" -description = "A collection of framework independent HTTP protocol utils." -optional = false -python-versions = ">=3.8.0" -groups = ["main"] -files = [ - {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f"}, - {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563"}, - {file = "httptools-0.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58"}, - {file = "httptools-0.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185"}, - {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142"}, - {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658"}, - {file = "httptools-0.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b"}, - {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1"}, - {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0"}, - {file = "httptools-0.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc"}, - {file = "httptools-0.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2"}, - {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837"}, - {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d"}, - {file = "httptools-0.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3"}, - {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0"}, - {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2"}, - {file = "httptools-0.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90"}, - {file = "httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503"}, - {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84"}, - {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb"}, - {file = "httptools-0.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949"}, - {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8e216a038d2d52ea13fdd9b9c9c7459fb80d78302b257828285eca1c773b99b3"}, - {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3e802e0b2378ade99cd666b5bffb8b2a7cc8f3d28988685dc300469ea8dd86cb"}, - {file = "httptools-0.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd3e488b447046e386a30f07af05f9b38d3d368d1f7b4d8f7e10af85393db97"}, - {file = "httptools-0.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe467eb086d80217b7584e61313ebadc8d187a4d95bb62031b7bab4b205c3ba3"}, - {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3c3b214ce057c54675b00108ac42bacf2ab8f85c58e3f324a4e963bbc46424f4"}, - {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ae5b97f690badd2ca27cbf668494ee1b6d34cf1c464271ef7bfa9ca6b83ffaf"}, - {file = "httptools-0.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:405784577ba6540fa7d6ff49e37daf104e04f4b4ff2d1ac0469eaa6a20fde084"}, - {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:95fb92dd3649f9cb139e9c56604cc2d7c7bf0fc2e7c8d7fbd58f96e35eddd2a3"}, - {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dcbab042cc3ef272adc11220517278519adf8f53fd3056d0e68f0a6f891ba94e"}, - {file = "httptools-0.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf2372e98406efb42e93bfe10f2948e467edfd792b015f1b4ecd897903d3e8d"}, - {file = "httptools-0.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:678fcbae74477a17d103b7cae78b74800d795d702083867ce160fc202104d0da"}, - {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e0b281cf5a125c35f7f6722b65d8542d2e57331be573e9e88bc8b0115c4a7a81"}, - {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95658c342529bba4e1d3d2b1a874db16c7cca435e8827422154c9da76ac4e13a"}, - {file = "httptools-0.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ebaec1bf683e4bf5e9fbb49b8cc36da482033596a415b3e4ebab5a4c0d7ec5e"}, - {file = "httptools-0.6.1.tar.gz", hash = "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a"}, -] - -[package.extras] -test = ["Cython (>=0.29.24,<0.30.0)"] - -[[package]] -name = "httpx" -version = "0.27.0" -description = "The next generation HTTP client." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, - {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, -] - -[package.dependencies] -anyio = "*" -certifi = "*" -h2 = {version = ">=3,<5", optional = true, markers = "extra == \"http2\""} -httpcore = "==1.*" -idna = "*" -sniffio = "*" - -[package.extras] -brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] - -[[package]] -name = "httpx-sse" -version = "0.4.0" -description = "Consume Server-Sent Event (SSE) messages with HTTPX." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721"}, - {file = "httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f"}, -] - -[[package]] -name = "huggingface-hub" -version = "0.23.4" -description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" -optional = false -python-versions = ">=3.8.0" -groups = ["main"] -files = [ - {file = "huggingface_hub-0.23.4-py3-none-any.whl", hash = "sha256:3a0b957aa87150addf0cc7bd71b4d954b78e749850e1e7fb29ebbd2db64ca037"}, - {file = "huggingface_hub-0.23.4.tar.gz", hash = "sha256:35d99016433900e44ae7efe1c209164a5a81dbbcd53a52f99c281dcd7ce22431"}, -] - -[package.dependencies] -filelock = "*" -fsspec = ">=2023.5.0" -packaging = ">=20.9" -pyyaml = ">=5.1" -requests = "*" -tqdm = ">=4.42.1" -typing-extensions = ">=3.7.4.3" - -[package.extras] -all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] -cli = ["InquirerPy (==0.3.4)"] -dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] -fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] -hf-transfer = ["hf-transfer (>=0.1.4)"] -inference = ["aiohttp", "minijinja (>=1.0)"] -quality = ["mypy (==1.5.1)", "ruff (>=0.3.0)"] -tensorflow = ["graphviz", "pydot", "tensorflow"] -tensorflow-testing = ["keras (<3.0)", "tensorflow"] -testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] -torch = ["safetensors", "torch"] -typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] - -[[package]] -name = "humanfriendly" -version = "10.0" -description = "Human friendly output for text interfaces using Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main"] -files = [ - {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"}, - {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"}, -] - -[package.dependencies] -pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""} - -[[package]] -name = "hyperframe" -version = "6.0.1" -description = "HTTP/2 framing layer for Python" -optional = false -python-versions = ">=3.6.1" -groups = ["main"] -files = [ - {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, - {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, -] - -[[package]] -name = "identify" -version = "2.6.0" -description = "File identification library for Python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "identify-2.6.0-py2.py3-none-any.whl", hash = "sha256:e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0"}, - {file = "identify-2.6.0.tar.gz", hash = "sha256:cb171c685bdc31bcc4c1734698736a7d5b6c8bf2e0c15117f4d469c8640ae5cf"}, -] - -[package.extras] -license = ["ukkonen"] - -[[package]] -name = "idna" -version = "3.7" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.5" -groups = ["main", "dev"] -files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, -] - -[[package]] -name = "importlib-metadata" -version = "7.1.0" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"}, - {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"}, -] - -[package.dependencies] -zipp = ">=0.5" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy ; platform_python_implementation != \"PyPy\"", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] - -[[package]] -name = "importlib-resources" -version = "6.4.0" -description = "Read resources from Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "importlib_resources-6.4.0-py3-none-any.whl", hash = "sha256:50d10f043df931902d4194ea07ec57960f66a80449ff867bfe782b4c486ba78c"}, - {file = "importlib_resources-6.4.0.tar.gz", hash = "sha256:cdb2b453b8046ca4e3798eb1d84f3cce1446a0e8e7b5ef4efb600f19fc398145"}, -] - -[package.dependencies] -zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["jaraco.test (>=5.4)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy ; platform_python_implementation != \"PyPy\"", "pytest-ruff (>=0.2.1)", "zipp (>=3.17)"] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -groups = ["dev"] -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - -[[package]] -name = "jinja2" -version = "3.1.4" -description = "A very fast and expressive template engine." -optional = true -python-versions = ">=3.7" -groups = ["main"] -markers = "extra == \"opensource\"" -files = [ - {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, - {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "jiter" -version = "0.5.0" -description = "Fast iterable JSON parser." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "jiter-0.5.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b599f4e89b3def9a94091e6ee52e1d7ad7bc33e238ebb9c4c63f211d74822c3f"}, - {file = "jiter-0.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a063f71c4b06225543dddadbe09d203dc0c95ba352d8b85f1221173480a71d5"}, - {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acc0d5b8b3dd12e91dd184b87273f864b363dfabc90ef29a1092d269f18c7e28"}, - {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c22541f0b672f4d741382a97c65609332a783501551445ab2df137ada01e019e"}, - {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63314832e302cc10d8dfbda0333a384bf4bcfce80d65fe99b0f3c0da8945a91a"}, - {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a25fbd8a5a58061e433d6fae6d5298777c0814a8bcefa1e5ecfff20c594bd749"}, - {file = "jiter-0.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:503b2c27d87dfff5ab717a8200fbbcf4714516c9d85558048b1fc14d2de7d8dc"}, - {file = "jiter-0.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6d1f3d27cce923713933a844872d213d244e09b53ec99b7a7fdf73d543529d6d"}, - {file = "jiter-0.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c95980207b3998f2c3b3098f357994d3fd7661121f30669ca7cb945f09510a87"}, - {file = "jiter-0.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:afa66939d834b0ce063f57d9895e8036ffc41c4bd90e4a99631e5f261d9b518e"}, - {file = "jiter-0.5.0-cp310-none-win32.whl", hash = "sha256:f16ca8f10e62f25fd81d5310e852df6649af17824146ca74647a018424ddeccf"}, - {file = "jiter-0.5.0-cp310-none-win_amd64.whl", hash = "sha256:b2950e4798e82dd9176935ef6a55cf6a448b5c71515a556da3f6b811a7844f1e"}, - {file = "jiter-0.5.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d4c8e1ed0ef31ad29cae5ea16b9e41529eb50a7fba70600008e9f8de6376d553"}, - {file = "jiter-0.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c6f16e21276074a12d8421692515b3fd6d2ea9c94fd0734c39a12960a20e85f3"}, - {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5280e68e7740c8c128d3ae5ab63335ce6d1fb6603d3b809637b11713487af9e6"}, - {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:583c57fc30cc1fec360e66323aadd7fc3edeec01289bfafc35d3b9dcb29495e4"}, - {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26351cc14507bdf466b5f99aba3df3143a59da75799bf64a53a3ad3155ecded9"}, - {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4829df14d656b3fb87e50ae8b48253a8851c707da9f30d45aacab2aa2ba2d614"}, - {file = "jiter-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a42a4bdcf7307b86cb863b2fb9bb55029b422d8f86276a50487982d99eed7c6e"}, - {file = "jiter-0.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04d461ad0aebf696f8da13c99bc1b3e06f66ecf6cfd56254cc402f6385231c06"}, - {file = "jiter-0.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e6375923c5f19888c9226582a124b77b622f8fd0018b843c45eeb19d9701c403"}, - {file = "jiter-0.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2cec323a853c24fd0472517113768c92ae0be8f8c384ef4441d3632da8baa646"}, - {file = "jiter-0.5.0-cp311-none-win32.whl", hash = "sha256:aa1db0967130b5cab63dfe4d6ff547c88b2a394c3410db64744d491df7f069bb"}, - {file = "jiter-0.5.0-cp311-none-win_amd64.whl", hash = "sha256:aa9d2b85b2ed7dc7697597dcfaac66e63c1b3028652f751c81c65a9f220899ae"}, - {file = "jiter-0.5.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9f664e7351604f91dcdd557603c57fc0d551bc65cc0a732fdacbf73ad335049a"}, - {file = "jiter-0.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:044f2f1148b5248ad2c8c3afb43430dccf676c5a5834d2f5089a4e6c5bbd64df"}, - {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:702e3520384c88b6e270c55c772d4bd6d7b150608dcc94dea87ceba1b6391248"}, - {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:528d742dcde73fad9d63e8242c036ab4a84389a56e04efd854062b660f559544"}, - {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8cf80e5fe6ab582c82f0c3331df27a7e1565e2dcf06265afd5173d809cdbf9ba"}, - {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:44dfc9ddfb9b51a5626568ef4e55ada462b7328996294fe4d36de02fce42721f"}, - {file = "jiter-0.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c451f7922992751a936b96c5f5b9bb9312243d9b754c34b33d0cb72c84669f4e"}, - {file = "jiter-0.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:308fce789a2f093dca1ff91ac391f11a9f99c35369117ad5a5c6c4903e1b3e3a"}, - {file = "jiter-0.5.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7f5ad4a7c6b0d90776fdefa294f662e8a86871e601309643de30bf94bb93a64e"}, - {file = "jiter-0.5.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ea189db75f8eca08807d02ae27929e890c7d47599ce3d0a6a5d41f2419ecf338"}, - {file = "jiter-0.5.0-cp312-none-win32.whl", hash = "sha256:e3bbe3910c724b877846186c25fe3c802e105a2c1fc2b57d6688b9f8772026e4"}, - {file = "jiter-0.5.0-cp312-none-win_amd64.whl", hash = "sha256:a586832f70c3f1481732919215f36d41c59ca080fa27a65cf23d9490e75b2ef5"}, - {file = "jiter-0.5.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:f04bc2fc50dc77be9d10f73fcc4e39346402ffe21726ff41028f36e179b587e6"}, - {file = "jiter-0.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6f433a4169ad22fcb550b11179bb2b4fd405de9b982601914ef448390b2954f3"}, - {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad4a6398c85d3a20067e6c69890ca01f68659da94d74c800298581724e426c7e"}, - {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6baa88334e7af3f4d7a5c66c3a63808e5efbc3698a1c57626541ddd22f8e4fbf"}, - {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ece0a115c05efca597c6d938f88c9357c843f8c245dbbb53361a1c01afd7148"}, - {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:335942557162ad372cc367ffaf93217117401bf930483b4b3ebdb1223dbddfa7"}, - {file = "jiter-0.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:649b0ee97a6e6da174bffcb3c8c051a5935d7d4f2f52ea1583b5b3e7822fbf14"}, - {file = "jiter-0.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f4be354c5de82157886ca7f5925dbda369b77344b4b4adf2723079715f823989"}, - {file = "jiter-0.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5206144578831a6de278a38896864ded4ed96af66e1e63ec5dd7f4a1fce38a3a"}, - {file = "jiter-0.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8120c60f8121ac3d6f072b97ef0e71770cc72b3c23084c72c4189428b1b1d3b6"}, - {file = "jiter-0.5.0-cp38-none-win32.whl", hash = "sha256:6f1223f88b6d76b519cb033a4d3687ca157c272ec5d6015c322fc5b3074d8a5e"}, - {file = "jiter-0.5.0-cp38-none-win_amd64.whl", hash = "sha256:c59614b225d9f434ea8fc0d0bec51ef5fa8c83679afedc0433905994fb36d631"}, - {file = "jiter-0.5.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:0af3838cfb7e6afee3f00dc66fa24695199e20ba87df26e942820345b0afc566"}, - {file = "jiter-0.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:550b11d669600dbc342364fd4adbe987f14d0bbedaf06feb1b983383dcc4b961"}, - {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:489875bf1a0ffb3cb38a727b01e6673f0f2e395b2aad3c9387f94187cb214bbf"}, - {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b250ca2594f5599ca82ba7e68785a669b352156260c5362ea1b4e04a0f3e2389"}, - {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ea18e01f785c6667ca15407cd6dabbe029d77474d53595a189bdc813347218e"}, - {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:462a52be85b53cd9bffd94e2d788a09984274fe6cebb893d6287e1c296d50653"}, - {file = "jiter-0.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92cc68b48d50fa472c79c93965e19bd48f40f207cb557a8346daa020d6ba973b"}, - {file = "jiter-0.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1c834133e59a8521bc87ebcad773608c6fa6ab5c7a022df24a45030826cf10bc"}, - {file = "jiter-0.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab3a71ff31cf2d45cb216dc37af522d335211f3a972d2fe14ea99073de6cb104"}, - {file = "jiter-0.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cccd3af9c48ac500c95e1bcbc498020c87e1781ff0345dd371462d67b76643eb"}, - {file = "jiter-0.5.0-cp39-none-win32.whl", hash = "sha256:368084d8d5c4fc40ff7c3cc513c4f73e02c85f6009217922d0823a48ee7adf61"}, - {file = "jiter-0.5.0-cp39-none-win_amd64.whl", hash = "sha256:ce03f7b4129eb72f1687fa11300fbf677b02990618428934662406d2a76742a1"}, - {file = "jiter-0.5.0.tar.gz", hash = "sha256:1d916ba875bcab5c5f7d927df998c4cb694d27dceddf3392e58beaf10563368a"}, -] - -[[package]] -name = "jmespath" -version = "1.0.1" -description = "JSON Matching Expressions" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, - {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, -] - -[[package]] -name = "joblib" -version = "1.4.2" -description = "Lightweight pipelining with Python functions" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"opensource\"" -files = [ - {file = "joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6"}, - {file = "joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"}, -] - -[[package]] -name = "jsonpatch" -version = "1.33" -description = "Apply JSON-Patches (RFC 6902)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" -groups = ["main"] -files = [ - {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, - {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, -] - -[package.dependencies] -jsonpointer = ">=1.9" - -[[package]] -name = "jsonpointer" -version = "3.0.0" -description = "Identify specific nodes in a JSON document (RFC 6901)" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"}, - {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, -] - -[[package]] -name = "kubernetes" -version = "30.1.0" -description = "Kubernetes python client" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "kubernetes-30.1.0-py2.py3-none-any.whl", hash = "sha256:e212e8b7579031dd2e512168b617373bc1e03888d41ac4e04039240a292d478d"}, - {file = "kubernetes-30.1.0.tar.gz", hash = "sha256:41e4c77af9f28e7a6c314e3bd06a8c6229ddd787cad684e0ab9f69b498e98ebc"}, -] - -[package.dependencies] -certifi = ">=14.5.14" -google-auth = ">=1.0.1" -oauthlib = ">=3.2.2" -python-dateutil = ">=2.5.3" -pyyaml = ">=5.4.1" -requests = "*" -requests-oauthlib = "*" -six = ">=1.9.0" -urllib3 = ">=1.24.2" -websocket-client = ">=0.32.0,<0.40.0 || >0.40.0,<0.41.dev0 || >=0.43.dev0" - -[package.extras] -adal = ["adal (>=1.0.2)"] - -[[package]] -name = "lancedb" -version = "0.6.13" -description = "lancedb" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"lancedb\"" -files = [ - {file = "lancedb-0.6.13-cp38-abi3-macosx_10_15_x86_64.whl", hash = "sha256:4667353ca7fa187e94cb0ca4c5f9577d65eb5160f6f3fe9e57902d86312c3869"}, - {file = "lancedb-0.6.13-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:2e22533fe6f6b2d7037dcdbbb4019a62402bbad4ce18395be68f4aa007bf8bc0"}, - {file = "lancedb-0.6.13-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:837eaceafb87e3ae4c261eef45c4f73715f892a36165572c3da621dbdb45afcf"}, - {file = "lancedb-0.6.13-cp38-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:61af2d72b2a2f0ea419874c3f32760fe5e51530da3be2d65251a0e6ded74419b"}, - {file = "lancedb-0.6.13-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:31b24e57ee313f4ce6255e45d42e8bee19b90ddcd13a9e07030ac04f76e7dfde"}, - {file = "lancedb-0.6.13-cp38-abi3-win_amd64.whl", hash = "sha256:b851182d8492b1e5b57a441af64c95da65ca30b045d6618dc7d203c6d60d70fa"}, -] - -[package.dependencies] -attrs = ">=21.3.0" -cachetools = "*" -deprecation = "*" -overrides = ">=0.7" -pydantic = ">=1.10" -pylance = "0.10.12" -ratelimiter = ">=1.0,<2.0" -requests = ">=2.31.0" -retry = ">=0.9.2" -semver = "*" -tqdm = ">=4.27.0" - -[package.extras] -azure = ["adlfs (>=2024.2.0)"] -clip = ["open-clip", "pillow", "torch"] -dev = ["pre-commit", "ruff"] -docs = ["mkdocs", "mkdocs-jupyter", "mkdocs-material", "mkdocstrings[python]"] -embeddings = ["awscli (>=1.29.57)", "boto3 (>=1.28.57)", "botocore (>=1.31.57)", "cohere", "google-generativeai", "huggingface-hub", "instructorembedding", "open-clip-torch", "openai (>=1.6.1)", "pillow", "sentence-transformers", "torch"] -tests = ["aiohttp", "boto3", "duckdb", "pandas (>=1.4)", "polars (>=0.19)", "pytest", "pytest-asyncio", "pytest-mock", "pytz", "tantivy"] - -[[package]] -name = "langchain" -version = "0.3.21" -description = "Building applications with LLMs through composability" -optional = false -python-versions = "<4.0,>=3.9" -groups = ["main"] -files = [ - {file = "langchain-0.3.21-py3-none-any.whl", hash = "sha256:c8bd2372440cc5d48cb50b2d532c2e24036124f1c467002ceb15bc7b86c92579"}, - {file = "langchain-0.3.21.tar.gz", hash = "sha256:a10c81f8c450158af90bf37190298d996208cfd15dd3accc1c585f068473d619"}, -] - -[package.dependencies] -async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} -langchain-core = ">=0.3.45,<1.0.0" -langchain-text-splitters = ">=0.3.7,<1.0.0" -langsmith = ">=0.1.17,<0.4" -pydantic = ">=2.7.4,<3.0.0" -PyYAML = ">=5.3" -requests = ">=2,<3" -SQLAlchemy = ">=1.4,<3" - -[package.extras] -anthropic = ["langchain-anthropic"] -aws = ["langchain-aws"] -azure-ai = ["langchain-azure-ai"] -cohere = ["langchain-cohere"] -community = ["langchain-community"] -deepseek = ["langchain-deepseek"] -fireworks = ["langchain-fireworks"] -google-genai = ["langchain-google-genai"] -google-vertexai = ["langchain-google-vertexai"] -groq = ["langchain-groq"] -huggingface = ["langchain-huggingface"] -mistralai = ["langchain-mistralai"] -ollama = ["langchain-ollama"] -openai = ["langchain-openai"] -together = ["langchain-together"] -xai = ["langchain-xai"] - -[[package]] -name = "langchain-aws" -version = "0.2.1" -description = "An integration package connecting AWS and LangChain" -optional = true -python-versions = "<4.0,>=3.9" -groups = ["main"] -markers = "extra == \"aws\"" -files = [ - {file = "langchain_aws-0.2.1-py3-none-any.whl", hash = "sha256:a866ca91d11798b06925cd39b7297db97e1ab438b91cbe2feeca443ed59e5b7a"}, - {file = "langchain_aws-0.2.1.tar.gz", hash = "sha256:e07ba5c16c7ef942072c3b3561cc517d34e01de8c05a9f9bc3d986e6b90f43b1"}, -] - -[package.dependencies] -boto3 = ">=1.34.131" -langchain-core = ">=0.3.2,<0.4" -numpy = [ - {version = ">=1,<2", markers = "python_version < \"3.12\""}, - {version = ">=1.26.0,<2.0.0", markers = "python_version >= \"3.12\""}, -] -pydantic = ">=2,<3" - -[[package]] -name = "langchain-cohere" -version = "0.3.0" -description = "An integration package connecting Cohere and LangChain" -optional = false -python-versions = "<4.0,>=3.9" -groups = ["main"] -files = [ - {file = "langchain_cohere-0.3.0-py3-none-any.whl", hash = "sha256:4c075fb227ed954e2be8b5448ee04e9850b88703799861d5bda8b014633ff069"}, - {file = "langchain_cohere-0.3.0.tar.gz", hash = "sha256:cf5b6d0f41df1294b76c7109adf371d9883ff50c4a07ed825221768a98d7bdd4"}, -] - -[package.dependencies] -cohere = ">=5.5.6,<6.0" -langchain-core = ">=0.3.0,<0.4" -langchain-experimental = ">=0.3.0" -pandas = ">=1.4.3" -pydantic = ">=2,<3" -tabulate = ">=0.9.0,<0.10.0" - -[package.extras] -langchain-community = ["langchain-community (>=0.3.0)"] - -[[package]] -name = "langchain-community" -version = "0.3.20" -description = "Community contributed LangChain integrations." -optional = false -python-versions = "<4.0,>=3.9" -groups = ["main"] -files = [ - {file = "langchain_community-0.3.20-py3-none-any.whl", hash = "sha256:ea3dbf37fbc21020eca8850627546f3c95a8770afc06c4142b40b9ba86b970f7"}, - {file = "langchain_community-0.3.20.tar.gz", hash = "sha256:bd83b4f2f818338423439aff3b5be362e1d686342ffada0478cd34c6f5ef5969"}, -] - -[package.dependencies] -aiohttp = ">=3.8.3,<4.0.0" -dataclasses-json = ">=0.5.7,<0.7" -httpx-sse = ">=0.4.0,<1.0.0" -langchain = ">=0.3.21,<1.0.0" -langchain-core = ">=0.3.45,<1.0.0" -langsmith = ">=0.1.125,<0.4" -numpy = ">=1.26.2,<3" -pydantic-settings = ">=2.4.0,<3.0.0" -PyYAML = ">=5.3" -requests = ">=2,<3" -SQLAlchemy = ">=1.4,<3" -tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10" - -[[package]] -name = "langchain-core" -version = "0.3.84" -description = "Building applications with LLMs through composability" -optional = false -python-versions = "<4.0.0,>=3.9.0" -groups = ["main"] -files = [ - {file = "langchain_core-0.3.84-py3-none-any.whl", hash = "sha256:d0b3a7b6473e30a2b3d4588ee09dc6471b8d38c46cd48f3e7c3d1ab6547f63cb"}, - {file = "langchain_core-0.3.84.tar.gz", hash = "sha256:814b75bfe67a8460a53f5839bae9505bbfffc7af6f1aa0a5155715563f5cc490"}, -] - -[package.dependencies] -jsonpatch = ">=1.33.0,<2.0.0" -langsmith = ">=0.3.45,<1.0.0" -packaging = ">=23.2.0,<26.0.0" -pydantic = ">=2.7.4,<3.0.0" -PyYAML = ">=5.3.0,<7.0.0" -tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0" -typing-extensions = ">=4.7.0,<5.0.0" -uuid-utils = ">=0.12.0,<1.0" - -[[package]] -name = "langchain-experimental" -version = "0.3.2" -description = "Building applications with LLMs through composability" -optional = false -python-versions = "<4.0,>=3.9" -groups = ["main"] -files = [ - {file = "langchain_experimental-0.3.2-py3-none-any.whl", hash = "sha256:b6a26f2a05e056a27ad30535ed306a6b9d8cc2e3c0326d15030d11b6e7505dbb"}, - {file = "langchain_experimental-0.3.2.tar.gz", hash = "sha256:d41cc28c46f58616d18a1230595929f80a58d1982c4053dc3afe7f1c03f22426"}, -] - -[package.dependencies] -langchain-community = ">=0.3.0,<0.4.0" -langchain-core = ">=0.3.6,<0.4.0" - -[[package]] -name = "langchain-google-vertexai" -version = "2.0.3" -description = "An integration package connecting Google VertexAI and LangChain" -optional = true -python-versions = "<4.0,>=3.9" -groups = ["main"] -markers = "extra == \"vertexai\"" -files = [ - {file = "langchain_google_vertexai-2.0.3-py3-none-any.whl", hash = "sha256:43835bed9f03f6969b3f8b73356c44d7898d209c69bd5124b0a80c35d8cebdd0"}, - {file = "langchain_google_vertexai-2.0.3.tar.gz", hash = "sha256:6f71061b578c0cd44fd5a147b61f66a1486bfc8b1dc69b4ac31e0f3c470d90d8"}, -] - -[package.dependencies] -google-cloud-aiplatform = ">=1.56.0,<2.0.0" -google-cloud-storage = ">=2.17.0,<3.0.0" -httpx = ">=0.27.0,<0.28.0" -httpx-sse = ">=0.4.0,<0.5.0" -langchain-core = ">=0.3.0,<0.4" -pydantic = ">=2,<3" - -[package.extras] -anthropic = ["anthropic[vertexai] (>=0.30.0,<1)"] -mistral = ["langchain-mistralai (>=0.2.0,<1)"] - -[[package]] -name = "langchain-mistralai" -version = "0.2.0" -description = "An integration package connecting Mistral and LangChain" -optional = true -python-versions = "<4.0,>=3.9" -groups = ["main"] -markers = "extra == \"mistralai\"" -files = [ - {file = "langchain_mistralai-0.2.0-py3-none-any.whl", hash = "sha256:1463093815f018d3a5860b4a41db25103235a12112e2c1e93c7576d09eee6382"}, - {file = "langchain_mistralai-0.2.0.tar.gz", hash = "sha256:f89ebec41daae18871c5820cf7105afb05333a23e9ee7b3199d9a8ecdbe30a97"}, -] - -[package.dependencies] -httpx = ">=0.25.2,<1" -httpx-sse = ">=0.3.1,<1" -langchain-core = ">=0.3.0,<0.4.0" -pydantic = ">=2,<3" -tokenizers = ">=0.15.1,<1" - -[[package]] -name = "langchain-openai" -version = "0.2.1" -description = "An integration package connecting OpenAI and LangChain" -optional = false -python-versions = "<4.0,>=3.9" -groups = ["main"] -files = [ - {file = "langchain_openai-0.2.1-py3-none-any.whl", hash = "sha256:215efa4526c88f8105f002b43b7cbf98cebd9baeb4f62c3b58faebdb578715bc"}, - {file = "langchain_openai-0.2.1.tar.gz", hash = "sha256:a131ea18736f1a8792925391b91a8c8bd834431ffc2055c92ba49f59c3dcaaf0"}, -] - -[package.dependencies] -langchain-core = ">=0.3,<0.4" -openai = ">=1.40.0,<2.0.0" -tiktoken = ">=0.7,<1" - -[[package]] -name = "langchain-text-splitters" -version = "0.3.7" -description = "LangChain text splitting utilities" -optional = false -python-versions = "<4.0,>=3.9" -groups = ["main"] -files = [ - {file = "langchain_text_splitters-0.3.7-py3-none-any.whl", hash = "sha256:31ba826013e3f563359d7c7f1e99b1cdb94897f665675ee505718c116e7e20ad"}, - {file = "langchain_text_splitters-0.3.7.tar.gz", hash = "sha256:7dbf0fb98e10bb91792a1d33f540e2287f9cc1dc30ade45b7aedd2d5cd3dc70b"}, -] - -[package.dependencies] -langchain-core = ">=0.3.45,<1.0.0" - -[[package]] -name = "langsmith" -version = "0.3.45" -description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "langsmith-0.3.45-py3-none-any.whl", hash = "sha256:5b55f0518601fa65f3bb6b1a3100379a96aa7b3ed5e9380581615ba9c65ed8ed"}, - {file = "langsmith-0.3.45.tar.gz", hash = "sha256:1df3c6820c73ed210b2c7bc5cdb7bfa19ddc9126cd03fdf0da54e2e171e6094d"}, -] - -[package.dependencies] -httpx = ">=0.23.0,<1" -orjson = {version = ">=3.9.14,<4.0.0", markers = "platform_python_implementation != \"PyPy\""} -packaging = ">=23.2" -pydantic = [ - {version = ">=1,<3", markers = "python_full_version < \"3.12.4\""}, - {version = ">=2.7.4,<3.0.0", markers = "python_full_version >= \"3.12.4\""}, -] -requests = ">=2,<3" -requests-toolbelt = ">=1.0.0,<2.0.0" -zstandard = ">=0.23.0,<0.24.0" - -[package.extras] -langsmith-pyo3 = ["langsmith-pyo3 (>=0.1.0rc2,<0.2.0)"] -openai-agents = ["openai-agents (>=0.0.3,<0.1)"] -otel = ["opentelemetry-api (>=1.30.0,<2.0.0)", "opentelemetry-exporter-otlp-proto-http (>=1.30.0,<2.0.0)", "opentelemetry-sdk (>=1.30.0,<2.0.0)"] -pytest = ["pytest (>=7.0.0)", "rich (>=13.9.4,<14.0.0)"] - -[[package]] -name = "mako" -version = "1.3.5" -description = "A super-fast templating language that borrows the best ideas from the existing templating languages." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "Mako-1.3.5-py3-none-any.whl", hash = "sha256:260f1dbc3a519453a9c856dedfe4beb4e50bd5a26d96386cb6c80856556bb91a"}, - {file = "Mako-1.3.5.tar.gz", hash = "sha256:48dbc20568c1d276a2698b36d968fa76161bf127194907ea6fc594fa81f943bc"}, -] - -[package.dependencies] -MarkupSafe = ">=0.9.2" - -[package.extras] -babel = ["Babel"] -lingua = ["lingua"] -testing = ["pytest"] - -[[package]] -name = "markdown-it-py" -version = "3.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, -] - -[package.dependencies] -mdurl = ">=0.1,<1.0" - -[package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -code-style = ["pre-commit (>=3.0,<4.0)"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] - -[[package]] -name = "markupsafe" -version = "2.1.5" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, - {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, -] - -[[package]] -name = "marshmallow" -version = "3.21.3" -description = "A lightweight library for converting complex datatypes to and from native Python datatypes." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "marshmallow-3.21.3-py3-none-any.whl", hash = "sha256:86ce7fb914aa865001a4b2092c4c2872d13bc347f3d42673272cabfdbad386f1"}, - {file = "marshmallow-3.21.3.tar.gz", hash = "sha256:4f57c5e050a54d66361e826f94fba213eb10b67b2fdb02c3e0343ce207ba1662"}, -] - -[package.dependencies] -packaging = ">=17.0" - -[package.extras] -dev = ["marshmallow[tests]", "pre-commit (>=3.5,<4.0)", "tox"] -docs = ["alabaster (==0.7.16)", "autodocsumm (==0.2.12)", "sphinx (==7.3.7)", "sphinx-issues (==4.1.0)", "sphinx-version-warning (==1.1.2)"] -tests = ["pytest", "pytz", "simplejson"] - -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, -] - -[[package]] -name = "mem0ai" -version = "0.1.54" -description = "Long-term memory for AI Agents" -optional = false -python-versions = "<4.0,>=3.9" -groups = ["main"] -files = [ - {file = "mem0ai-0.1.54-py3-none-any.whl", hash = "sha256:026c3262d714ebe536fb796c53e553051dbe6da66a8a313587efebfd420a0f7a"}, - {file = "mem0ai-0.1.54.tar.gz", hash = "sha256:f7a0dd2303e59a0131c1dea72058ba165d91e2b3e36d159cc7bbbb062610cc87"}, -] - -[package.dependencies] -openai = ">=1.33.0,<2.0.0" -posthog = ">=3.5.0,<4.0.0" -pydantic = ">=2.7.3,<3.0.0" -pytz = ">=2024.1,<2025.0" -qdrant-client = ">=1.9.1,<2.0.0" -sqlalchemy = ">=2.0.31,<3.0.0" - -[package.extras] -graph = ["langchain-community (>=0.3.1,<0.4.0)", "neo4j (>=5.23.1,<6.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)"] - -[[package]] -name = "milvus-lite" -version = "2.4.8" -description = "A lightweight version of Milvus wrapped with Python." -optional = true -python-versions = ">=3.7" -groups = ["main"] -markers = "extra == \"milvus\"" -files = [ - {file = "milvus_lite-2.4.8-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:b7e90b34b214884cd44cdc112ab243d4cb197b775498355e2437b6cafea025fe"}, - {file = "milvus_lite-2.4.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:519dfc62709d8f642d98a1c5b1dcde7080d107e6e312d677fef5a3412a40ac08"}, - {file = "milvus_lite-2.4.8-py3-none-manylinux2014_aarch64.whl", hash = "sha256:b21f36d24cbb0e920b4faad607019bb28c1b2c88b4d04680ac8c7697a4ae8a4d"}, - {file = "milvus_lite-2.4.8-py3-none-manylinux2014_x86_64.whl", hash = "sha256:08332a2b9abfe7c4e1d7926068937e46f8fb81f2707928b7bc02c9dc99cebe41"}, -] - -[package.dependencies] -tqdm = "*" - -[[package]] -name = "mmh3" -version = "4.1.0" -description = "Python extension for MurmurHash (MurmurHash3), a set of fast and robust hash functions." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:be5ac76a8b0cd8095784e51e4c1c9c318c19edcd1709a06eb14979c8d850c31a"}, - {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98a49121afdfab67cd80e912b36404139d7deceb6773a83620137aaa0da5714c"}, - {file = "mmh3-4.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5259ac0535874366e7d1a5423ef746e0d36a9e3c14509ce6511614bdc5a7ef5b"}, - {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5950827ca0453a2be357696da509ab39646044e3fa15cad364eb65d78797437"}, - {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1dd0f652ae99585b9dd26de458e5f08571522f0402155809fd1dc8852a613a39"}, - {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99d25548070942fab1e4a6f04d1626d67e66d0b81ed6571ecfca511f3edf07e6"}, - {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53db8d9bad3cb66c8f35cbc894f336273f63489ce4ac416634932e3cbe79eb5b"}, - {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75da0f615eb55295a437264cc0b736753f830b09d102aa4c2a7d719bc445ec05"}, - {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b926b07fd678ea84b3a2afc1fa22ce50aeb627839c44382f3d0291e945621e1a"}, - {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c5b053334f9b0af8559d6da9dc72cef0a65b325ebb3e630c680012323c950bb6"}, - {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:5bf33dc43cd6de2cb86e0aa73a1cc6530f557854bbbe5d59f41ef6de2e353d7b"}, - {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fa7eacd2b830727ba3dd65a365bed8a5c992ecd0c8348cf39a05cc77d22f4970"}, - {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:42dfd6742b9e3eec599f85270617debfa0bbb913c545bb980c8a4fa7b2d047da"}, - {file = "mmh3-4.1.0-cp310-cp310-win32.whl", hash = "sha256:2974ad343f0d39dcc88e93ee6afa96cedc35a9883bc067febd7ff736e207fa47"}, - {file = "mmh3-4.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:74699a8984ded645c1a24d6078351a056f5a5f1fe5838870412a68ac5e28d865"}, - {file = "mmh3-4.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:f0dc874cedc23d46fc488a987faa6ad08ffa79e44fb08e3cd4d4cf2877c00a00"}, - {file = "mmh3-4.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3280a463855b0eae64b681cd5b9ddd9464b73f81151e87bb7c91a811d25619e6"}, - {file = "mmh3-4.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:97ac57c6c3301769e757d444fa7c973ceb002cb66534b39cbab5e38de61cd896"}, - {file = "mmh3-4.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a7b6502cdb4dbd880244818ab363c8770a48cdccecf6d729ade0241b736b5ec0"}, - {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52ba2da04671a9621580ddabf72f06f0e72c1c9c3b7b608849b58b11080d8f14"}, - {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a5fef4c4ecc782e6e43fbeab09cff1bac82c998a1773d3a5ee6a3605cde343e"}, - {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5135358a7e00991f73b88cdc8eda5203bf9de22120d10a834c5761dbeb07dd13"}, - {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cff9ae76a54f7c6fe0167c9c4028c12c1f6de52d68a31d11b6790bb2ae685560"}, - {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f02576a4d106d7830ca90278868bf0983554dd69183b7bbe09f2fcd51cf54f"}, - {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:073d57425a23721730d3ff5485e2da489dd3c90b04e86243dd7211f889898106"}, - {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:71e32ddec7f573a1a0feb8d2cf2af474c50ec21e7a8263026e8d3b4b629805db"}, - {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7cbb20b29d57e76a58b40fd8b13a9130db495a12d678d651b459bf61c0714cea"}, - {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:a42ad267e131d7847076bb7e31050f6c4378cd38e8f1bf7a0edd32f30224d5c9"}, - {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4a013979fc9390abadc445ea2527426a0e7a4495c19b74589204f9b71bcaafeb"}, - {file = "mmh3-4.1.0-cp311-cp311-win32.whl", hash = "sha256:1d3b1cdad7c71b7b88966301789a478af142bddcb3a2bee563f7a7d40519a00f"}, - {file = "mmh3-4.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0dc6dc32eb03727467da8e17deffe004fbb65e8b5ee2b502d36250d7a3f4e2ec"}, - {file = "mmh3-4.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:9ae3a5c1b32dda121c7dc26f9597ef7b01b4c56a98319a7fe86c35b8bc459ae6"}, - {file = "mmh3-4.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0033d60c7939168ef65ddc396611077a7268bde024f2c23bdc283a19123f9e9c"}, - {file = "mmh3-4.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d6af3e2287644b2b08b5924ed3a88c97b87b44ad08e79ca9f93d3470a54a41c5"}, - {file = "mmh3-4.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d82eb4defa245e02bb0b0dc4f1e7ee284f8d212633389c91f7fba99ba993f0a2"}, - {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba245e94b8d54765e14c2d7b6214e832557e7856d5183bc522e17884cab2f45d"}, - {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb04e2feeabaad6231e89cd43b3d01a4403579aa792c9ab6fdeef45cc58d4ec0"}, - {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e3b1a27def545ce11e36158ba5d5390cdbc300cfe456a942cc89d649cf7e3b2"}, - {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce0ab79ff736d7044e5e9b3bfe73958a55f79a4ae672e6213e92492ad5e734d5"}, - {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b02268be6e0a8eeb8a924d7db85f28e47344f35c438c1e149878bb1c47b1cd3"}, - {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:deb887f5fcdaf57cf646b1e062d56b06ef2f23421c80885fce18b37143cba828"}, - {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99dd564e9e2b512eb117bd0cbf0f79a50c45d961c2a02402787d581cec5448d5"}, - {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:08373082dfaa38fe97aa78753d1efd21a1969e51079056ff552e687764eafdfe"}, - {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:54b9c6a2ea571b714e4fe28d3e4e2db37abfd03c787a58074ea21ee9a8fd1740"}, - {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a7b1edf24c69e3513f879722b97ca85e52f9032f24a52284746877f6a7304086"}, - {file = "mmh3-4.1.0-cp312-cp312-win32.whl", hash = "sha256:411da64b951f635e1e2284b71d81a5a83580cea24994b328f8910d40bed67276"}, - {file = "mmh3-4.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:bebc3ecb6ba18292e3d40c8712482b4477abd6981c2ebf0e60869bd90f8ac3a9"}, - {file = "mmh3-4.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:168473dd608ade6a8d2ba069600b35199a9af837d96177d3088ca91f2b3798e3"}, - {file = "mmh3-4.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:372f4b7e1dcde175507640679a2a8790185bb71f3640fc28a4690f73da986a3b"}, - {file = "mmh3-4.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:438584b97f6fe13e944faf590c90fc127682b57ae969f73334040d9fa1c7ffa5"}, - {file = "mmh3-4.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6e27931b232fc676675fac8641c6ec6b596daa64d82170e8597f5a5b8bdcd3b6"}, - {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:571a92bad859d7b0330e47cfd1850b76c39b615a8d8e7aa5853c1f971fd0c4b1"}, - {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a69d6afe3190fa08f9e3a58e5145549f71f1f3fff27bd0800313426929c7068"}, - {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:afb127be0be946b7630220908dbea0cee0d9d3c583fa9114a07156f98566dc28"}, - {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:940d86522f36348ef1a494cbf7248ab3f4a1638b84b59e6c9e90408bd11ad729"}, - {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3dcccc4935686619a8e3d1f7b6e97e3bd89a4a796247930ee97d35ea1a39341"}, - {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01bb9b90d61854dfc2407c5e5192bfb47222d74f29d140cb2dd2a69f2353f7cc"}, - {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bcb1b8b951a2c0b0fb8a5426c62a22557e2ffc52539e0a7cc46eb667b5d606a9"}, - {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6477a05d5e5ab3168e82e8b106e316210ac954134f46ec529356607900aea82a"}, - {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:da5892287e5bea6977364b15712a2573c16d134bc5fdcdd4cf460006cf849278"}, - {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:99180d7fd2327a6fffbaff270f760576839dc6ee66d045fa3a450f3490fda7f5"}, - {file = "mmh3-4.1.0-cp38-cp38-win32.whl", hash = "sha256:9b0d4f3949913a9f9a8fb1bb4cc6ecd52879730aab5ff8c5a3d8f5b593594b73"}, - {file = "mmh3-4.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:598c352da1d945108aee0c3c3cfdd0e9b3edef74108f53b49d481d3990402169"}, - {file = "mmh3-4.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:475d6d1445dd080f18f0f766277e1237fa2914e5fe3307a3b2a3044f30892103"}, - {file = "mmh3-4.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5ca07c41e6a2880991431ac717c2a049056fff497651a76e26fc22224e8b5732"}, - {file = "mmh3-4.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ebe052fef4bbe30c0548d12ee46d09f1b69035ca5208a7075e55adfe091be44"}, - {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaefd42e85afb70f2b855a011f7b4d8a3c7e19c3f2681fa13118e4d8627378c5"}, - {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0ae43caae5a47afe1b63a1ae3f0986dde54b5fb2d6c29786adbfb8edc9edfb"}, - {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6218666f74c8c013c221e7f5f8a693ac9cf68e5ac9a03f2373b32d77c48904de"}, - {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac59294a536ba447b5037f62d8367d7d93b696f80671c2c45645fa9f1109413c"}, - {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086844830fcd1e5c84fec7017ea1ee8491487cfc877847d96f86f68881569d2e"}, - {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e42b38fad664f56f77f6fbca22d08450f2464baa68acdbf24841bf900eb98e87"}, - {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d08b790a63a9a1cde3b5d7d733ed97d4eb884bfbc92f075a091652d6bfd7709a"}, - {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:73ea4cc55e8aea28c86799ecacebca09e5f86500414870a8abaedfcbaf74d288"}, - {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:f90938ff137130e47bcec8dc1f4ceb02f10178c766e2ef58a9f657ff1f62d124"}, - {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:aa1f13e94b8631c8cd53259250556edcf1de71738936b60febba95750d9632bd"}, - {file = "mmh3-4.1.0-cp39-cp39-win32.whl", hash = "sha256:a3b680b471c181490cf82da2142029edb4298e1bdfcb67c76922dedef789868d"}, - {file = "mmh3-4.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:fefef92e9c544a8dbc08f77a8d1b6d48006a750c4375bbcd5ff8199d761e263b"}, - {file = "mmh3-4.1.0-cp39-cp39-win_arm64.whl", hash = "sha256:8e2c1f6a2b41723a4f82bd5a762a777836d29d664fc0095f17910bea0adfd4a6"}, - {file = "mmh3-4.1.0.tar.gz", hash = "sha256:a1cf25348b9acd229dda464a094d6170f47d2850a1fcb762a3b6172d2ce6ca4a"}, -] - -[package.extras] -test = ["mypy (>=1.0)", "pytest (>=7.0.0)"] - -[[package]] -name = "mock" -version = "5.1.0" -description = "Rolling backport of unittest.mock for all Pythons" -optional = false -python-versions = ">=3.6" -groups = ["dev"] -files = [ - {file = "mock-5.1.0-py3-none-any.whl", hash = "sha256:18c694e5ae8a208cdb3d2c20a993ca1a7b0efa258c247a1e565150f477f83744"}, - {file = "mock-5.1.0.tar.gz", hash = "sha256:5e96aad5ccda4718e0a229ed94b2024df75cc2d55575ba5762d31f5767b8767d"}, -] - -[package.extras] -build = ["blurb", "twine", "wheel"] -docs = ["sphinx"] -test = ["pytest", "pytest-cov"] - -[[package]] -name = "monotonic" -version = "1.6" -description = "An implementation of time.monotonic() for Python 2 & < 3.3" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "monotonic-1.6-py2.py3-none-any.whl", hash = "sha256:68687e19a14f11f26d140dd5c86f3dba4bf5df58003000ed467e0e2a69bca96c"}, - {file = "monotonic-1.6.tar.gz", hash = "sha256:3a55207bcfed53ddd5c5bae174524062935efed17792e9de2ad0205ce9ad63f7"}, -] - -[[package]] -name = "mpmath" -version = "1.3.0" -description = "Python library for arbitrary-precision floating-point arithmetic" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"}, - {file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"}, -] - -[package.extras] -develop = ["codecov", "pycodestyle", "pytest (>=4.6)", "pytest-cov", "wheel"] -docs = ["sphinx"] -gmpy = ["gmpy2 (>=2.1.0a4) ; platform_python_implementation != \"PyPy\""] -tests = ["pytest (>=4.6)"] - -[[package]] -name = "multidict" -version = "6.0.5" -description = "multidict implementation" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, - {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, - {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, - {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, - {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, - {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, - {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, - {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, - {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, - {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, - {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, - {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, - {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, - {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, - {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, - {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, -] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -groups = ["main", "dev"] -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "mysql-connector-python" -version = "8.4.0" -description = "MySQL driver written in Python" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"mysql\"" -files = [ - {file = "mysql-connector-python-8.4.0.tar.gz", hash = "sha256:42542d131d63c78416d410fdc9e84b9acb960d715c2e7b28c57ac9577c6d8165"}, - {file = "mysql_connector_python-8.4.0-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:c0a2688d95d53cfbea9352ed61926b47bc9042570570fb8fe0a8d19b1e20f1c4"}, - {file = "mysql_connector_python-8.4.0-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:276bae0d5d44abb7ba1205003b55628e4e6f1d399f1825d518bc607320997b1f"}, - {file = "mysql_connector_python-8.4.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:a6d24ea29b3c2bdbba6861590de557665420bfb938f74b5cecc630bac5457d35"}, - {file = "mysql_connector_python-8.4.0-cp310-cp310-manylinux_2_17_x86_64.whl", hash = "sha256:b7876358d9e51f25edc492088c4ce16cd14c2db87c279a965b0f9c327723359c"}, - {file = "mysql_connector_python-8.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:085024bf12d15f9b428938fdbeb50bd9b15dda9c4d3a474e6df061cb08713e6a"}, - {file = "mysql_connector_python-8.4.0-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4e83fc8ed95005b171ffa36a289dac48625048263b09b56718e8395539ea07d9"}, - {file = "mysql_connector_python-8.4.0-cp311-cp311-macosx_13_0_x86_64.whl", hash = "sha256:cd89d1c8c2d1e33e5ac2d4eac5813422c150a8427fb60a16c59be18c29dd9a94"}, - {file = "mysql_connector_python-8.4.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:76c13fde35a038afe50550a9af7b31b28ca3a04cce06f3030980afb20460d28c"}, - {file = "mysql_connector_python-8.4.0-cp311-cp311-manylinux_2_17_x86_64.whl", hash = "sha256:accf10425c6af39a9595a47e7119ebcbcd7351f7df28755dbee01bca5a605b7c"}, - {file = "mysql_connector_python-8.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cda868bb4e1641362d148f5b0d2a86188cffa2f7188831589781b13f2df6f51a"}, - {file = "mysql_connector_python-8.4.0-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:3ae951f2e16d089975cb9f05b3f3e58807dc33a2e5a627047bba1c8ad5439d82"}, - {file = "mysql_connector_python-8.4.0-cp312-cp312-macosx_13_0_x86_64.whl", hash = "sha256:af40b5bdd91547d3dbf5fa62bde37e9e840bd7cba3b9246b55c09e6a1cde536f"}, - {file = "mysql_connector_python-8.4.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:bb4f3edab78f3fd6f80c6c0a9e5a533704044fc01bfb9e8736e1a993f74aa42d"}, - {file = "mysql_connector_python-8.4.0-cp312-cp312-manylinux_2_17_x86_64.whl", hash = "sha256:e549674c72b596a7386f4a76bbac2ee9581f6632e6713618a70468713b162964"}, - {file = "mysql_connector_python-8.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:aed505adc76b58282c76e6cbf3da195be0f84029a41f05c470be977481896074"}, - {file = "mysql_connector_python-8.4.0-cp38-cp38-macosx_13_0_x86_64.whl", hash = "sha256:d343a4a8133ae9561bd537fc8cdbcab74a0607a5f40698569010fa3c7d4a048f"}, - {file = "mysql_connector_python-8.4.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:74b1759d8bd9ccd4296dc2e5abe22ec7efbd1ad12a9032c2cb4d17fa5d0ca6e0"}, - {file = "mysql_connector_python-8.4.0-cp38-cp38-manylinux_2_17_x86_64.whl", hash = "sha256:e6d5a418ef124dd1b18a73fd89431a1862ce7bf68f61275c7d006e8e2f8afcd2"}, - {file = "mysql_connector_python-8.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:427a84027b8314c73f5ff3eb1abdc709a8201b44a491d7b580bdf430b4820a16"}, - {file = "mysql_connector_python-8.4.0-cp39-cp39-macosx_13_0_arm64.whl", hash = "sha256:44a99d44a925ea29c2e423e6d8b1d97ce740c3078d8b41923a81bbcd0a821972"}, - {file = "mysql_connector_python-8.4.0-cp39-cp39-macosx_13_0_x86_64.whl", hash = "sha256:ed276c4e7907da0ad95a9ad122004294d6fb425127064af2ae880033b8e72166"}, - {file = "mysql_connector_python-8.4.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:2b5c6fea6513cf208c7116a4a5e36b3ae54e0d37f324a7cfe43fb01cfdf03be6"}, - {file = "mysql_connector_python-8.4.0-cp39-cp39-manylinux_2_17_x86_64.whl", hash = "sha256:651c7824af57eb50f4a79ea04bf6f453b24381e1bb56eee45c0035b4c0c624c0"}, - {file = "mysql_connector_python-8.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:655dccbdc0e2943e62cf69e10a024329248b17b58bfac59c60fd2103db3ba0b0"}, - {file = "mysql_connector_python-8.4.0-py2.py3-none-any.whl", hash = "sha256:35939c4ff28f395a5550bae67bafa4d1658ea72ea3206f457fff64a0fbec17e4"}, -] - -[package.extras] -dns-srv = ["dnspython (>=1.16.0,<=2.3.0)"] -fido2 = ["fido2 (==1.1.2)"] -gssapi = ["gssapi (>=1.6.9,<=1.8.2)"] -opentelemetry = ["Deprecated (>=1.2.6)", "typing-extensions (>=3.7.4)", "zipp (>=0.5)"] - -[[package]] -name = "networkx" -version = "3.2.1" -description = "Python package for creating and manipulating graphs and networks" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"opensource\"" -files = [ - {file = "networkx-3.2.1-py3-none-any.whl", hash = "sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2"}, - {file = "networkx-3.2.1.tar.gz", hash = "sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6"}, -] - -[package.extras] -default = ["matplotlib (>=3.5)", "numpy (>=1.22)", "pandas (>=1.4)", "scipy (>=1.9,!=1.11.0,!=1.11.1)"] -developer = ["changelist (==0.4)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"] -doc = ["nb2plots (>=0.7)", "nbconvert (<7.9)", "numpydoc (>=1.6)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.14)", "sphinx (>=7)", "sphinx-gallery (>=0.14)", "texext (>=0.6.7)"] -extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.11)", "sympy (>=1.10)"] -test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] - -[[package]] -name = "nodeenv" -version = "1.9.1" -description = "Node.js virtual environment builder" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["dev"] -files = [ - {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, - {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, -] - -[[package]] -name = "numpy" -version = "1.26.4" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, - {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, - {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, - {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, - {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, - {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, - {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, - {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, - {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, - {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, - {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, - {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, - {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, - {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, - {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, - {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, - {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, - {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, - {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, - {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, - {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, - {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, - {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, - {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, - {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, - {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, - {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, - {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, - {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, - {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, - {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, - {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, - {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, -] - -[[package]] -name = "nvidia-cublas" -version = "13.1.0.3" -description = "CUBLAS native runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and python_version >= \"3.10\"" -files = [ - {file = "nvidia_cublas-13.1.0.3-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:c86fc7f7ae36d7528288c5d88098edcb7b02c633d262e7ddbb86b0ad91be5df2"}, - {file = "nvidia_cublas-13.1.0.3-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:ee8722c1f0145ab246bccb9e452153b5e0515fd094c3678df50b2a0888b8b171"}, - {file = "nvidia_cublas-13.1.0.3-py3-none-win_amd64.whl", hash = "sha256:2a3b94a37def342471c59fad7856caee4926809a72dd5270155d6a31b5b277be"}, -] - -[[package]] -name = "nvidia-cublas-cu12" -version = "12.8.4.1" -description = "CUBLAS native runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_cublas_cu12-12.8.4.1-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:b86f6dd8935884615a0683b663891d43781b819ac4f2ba2b0c9604676af346d0"}, - {file = "nvidia_cublas_cu12-12.8.4.1-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:8ac4e771d5a348c551b2a426eda6193c19aa630236b418086020df5ba9667142"}, - {file = "nvidia_cublas_cu12-12.8.4.1-py3-none-win_amd64.whl", hash = "sha256:47e9b82132fa8d2b4944e708049229601448aaad7e6f296f630f2d1a32de35af"}, -] - -[[package]] -name = "nvidia-cuda-cupti" -version = "13.0.85" -description = "CUDA profiling tools runtime libs." -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and (sys_platform == \"linux\" or sys_platform == \"win32\") and python_version >= \"3.10\"" -files = [ - {file = "nvidia_cuda_cupti-13.0.85-py3-none-manylinux_2_25_aarch64.whl", hash = "sha256:796bd679890ee55fb14a94629b698b6db54bcfd833d391d5e94017dd9d7d3151"}, - {file = "nvidia_cuda_cupti-13.0.85-py3-none-manylinux_2_25_x86_64.whl", hash = "sha256:4eb01c08e859bf924d222250d2e8f8b8ff6d3db4721288cf35d14252a4d933c8"}, - {file = "nvidia_cuda_cupti-13.0.85-py3-none-win_amd64.whl", hash = "sha256:683f58d301548deeefcb8f6fac1b8d907691b9d8b18eccab417f51e362102f00"}, -] - -[[package]] -name = "nvidia-cuda-cupti-cu12" -version = "12.8.90" -description = "CUDA profiling tools runtime libs." -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_cuda_cupti_cu12-12.8.90-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4412396548808ddfed3f17a467b104ba7751e6b58678a4b840675c56d21cf7ed"}, - {file = "nvidia_cuda_cupti_cu12-12.8.90-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ea0cb07ebda26bb9b29ba82cda34849e73c166c18162d3913575b0c9db9a6182"}, - {file = "nvidia_cuda_cupti_cu12-12.8.90-py3-none-win_amd64.whl", hash = "sha256:bb479dcdf7e6d4f8b0b01b115260399bf34154a1a2e9fe11c85c517d87efd98e"}, -] - -[[package]] -name = "nvidia-cuda-nvrtc" -version = "13.0.88" -description = "NVRTC native runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and (sys_platform == \"linux\" or sys_platform == \"win32\") and python_version >= \"3.10\"" -files = [ - {file = "nvidia_cuda_nvrtc-13.0.88-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:ad9b6d2ead2435f11cbb6868809d2adeeee302e9bb94bcf0539c7a40d80e8575"}, - {file = "nvidia_cuda_nvrtc-13.0.88-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d27f20a0ca67a4bb34268a5e951033496c5b74870b868bacd046b1b8e0c3267b"}, - {file = "nvidia_cuda_nvrtc-13.0.88-py3-none-win_amd64.whl", hash = "sha256:6bcd4e7f8e205cbe644f5a98f2f799bef9556fefc89dd786e79a16312ce49872"}, -] - -[[package]] -name = "nvidia-cuda-nvrtc-cu12" -version = "12.8.93" -description = "NVRTC native runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_cuda_nvrtc_cu12-12.8.93-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:a7756528852ef889772a84c6cd89d41dfa74667e24cca16bb31f8f061e3e9994"}, - {file = "nvidia_cuda_nvrtc_cu12-12.8.93-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fc1fec1e1637854b4c0a65fb9a8346b51dd9ee69e61ebaccc82058441f15bce8"}, - {file = "nvidia_cuda_nvrtc_cu12-12.8.93-py3-none-win_amd64.whl", hash = "sha256:7a4b6b2904850fe78e0bd179c4b655c404d4bb799ef03ddc60804247099ae909"}, -] - -[[package]] -name = "nvidia-cuda-runtime" -version = "13.0.96" -description = "CUDA Runtime native Libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and (sys_platform == \"linux\" or sys_platform == \"win32\") and python_version >= \"3.10\"" -files = [ - {file = "nvidia_cuda_runtime-13.0.96-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ef9bcbe90493a2b9d810e43d249adb3d02e98dd30200d86607d8d02687c43f55"}, - {file = "nvidia_cuda_runtime-13.0.96-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7f82250d7782aa23b6cfe765ecc7db554bd3c2870c43f3d1821f1d18aebf0548"}, - {file = "nvidia_cuda_runtime-13.0.96-py3-none-win_amd64.whl", hash = "sha256:f79298c8a098cec150a597c8eba58ecdab96e3bdc4b9bc4f9983635031740492"}, -] - -[[package]] -name = "nvidia-cuda-runtime-cu12" -version = "12.8.90" -description = "CUDA Runtime native Libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_cuda_runtime_cu12-12.8.90-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:52bf7bbee900262ffefe5e9d5a2a69a30d97e2bc5bb6cc866688caa976966e3d"}, - {file = "nvidia_cuda_runtime_cu12-12.8.90-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:adade8dcbd0edf427b7204d480d6066d33902cab2a4707dcfc48a2d0fd44ab90"}, - {file = "nvidia_cuda_runtime_cu12-12.8.90-py3-none-win_amd64.whl", hash = "sha256:c0c6027f01505bfed6c3b21ec546f69c687689aad5f1a377554bc6ca4aa993a8"}, -] - -[[package]] -name = "nvidia-cudnn-cu12" -version = "9.10.2.21" -description = "cuDNN runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_cudnn_cu12-9.10.2.21-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:c9132cc3f8958447b4910a1720036d9eff5928cc3179b0a51fb6d167c6cc87d8"}, - {file = "nvidia_cudnn_cu12-9.10.2.21-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:949452be657fa16687d0930933f032835951ef0892b37d2d53824d1a84dc97a8"}, - {file = "nvidia_cudnn_cu12-9.10.2.21-py3-none-win_amd64.whl", hash = "sha256:c6288de7d63e6cf62988f0923f96dc339cea362decb1bf5b3141883392a7d65e"}, -] - -[package.dependencies] -nvidia-cublas-cu12 = "*" - -[[package]] -name = "nvidia-cudnn-cu13" -version = "9.19.0.56" -description = "cuDNN runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and python_version >= \"3.10\"" -files = [ - {file = "nvidia_cudnn_cu13-9.19.0.56-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:6ed29ffaee1176c612daf442e4dd6cfeb6a0caa43ddcbeb59da94953030b1be4"}, - {file = "nvidia_cudnn_cu13-9.19.0.56-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:d20e1734305e9d68889a96e3f35094d733ff1f83932ebe462753973e53a572bf"}, - {file = "nvidia_cudnn_cu13-9.19.0.56-py3-none-win_amd64.whl", hash = "sha256:40d8c375005bcb01495f8edf375230b203a411a0c05fb6dc92a3781edcb23eac"}, -] - -[package.dependencies] -nvidia-cublas = "*" - -[[package]] -name = "nvidia-cufft" -version = "12.0.0.61" -description = "CUFFT native runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and (sys_platform == \"linux\" or sys_platform == \"win32\") and python_version >= \"3.10\"" -files = [ - {file = "nvidia_cufft-12.0.0.61-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2708c852ef8cd89d1d2068bdbece0aa188813a0c934db3779b9b1faa8442e5f5"}, - {file = "nvidia_cufft-12.0.0.61-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6c44f692dce8fd5ffd3e3df134b6cdb9c2f72d99cf40b62c32dde45eea9ddad3"}, - {file = "nvidia_cufft-12.0.0.61-py3-none-win_amd64.whl", hash = "sha256:2abce5b39d2f5ae12730fb7e5db6696533e36c26e2d3e8fd1750bdd2853364eb"}, -] - -[package.dependencies] -nvidia-nvjitlink = "*" - -[[package]] -name = "nvidia-cufft-cu12" -version = "11.3.3.83" -description = "CUFFT native runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_cufft_cu12-11.3.3.83-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:848ef7224d6305cdb2a4df928759dca7b1201874787083b6e7550dd6765ce69a"}, - {file = "nvidia_cufft_cu12-11.3.3.83-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d2dd21ec0b88cf61b62e6b43564355e5222e4a3fb394cac0db101f2dd0d4f74"}, - {file = "nvidia_cufft_cu12-11.3.3.83-py3-none-win_amd64.whl", hash = "sha256:7a64a98ef2a7c47f905aaf8931b69a3a43f27c55530c698bb2ed7c75c0b42cb7"}, -] - -[package.dependencies] -nvidia-nvjitlink-cu12 = "*" - -[[package]] -name = "nvidia-cufile" -version = "1.15.1.6" -description = "cuFile GPUDirect libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and sys_platform == \"linux\" and python_version >= \"3.10\"" -files = [ - {file = "nvidia_cufile-1.15.1.6-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:08a3ecefae5a01c7f5117351c64f17c7c62efa5fffdbe24fc7d298da19cd0b44"}, - {file = "nvidia_cufile-1.15.1.6-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:bdc0deedc61f548bddf7733bdc216456c2fdb101d020e1ab4b88d232d5e2f6d1"}, -] - -[[package]] -name = "nvidia-cufile-cu12" -version = "1.13.1.3" -description = "cuFile GPUDirect libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_cufile_cu12-1.13.1.3-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1d069003be650e131b21c932ec3d8969c1715379251f8d23a1860554b1cb24fc"}, - {file = "nvidia_cufile_cu12-1.13.1.3-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:4beb6d4cce47c1a0f1013d72e02b0994730359e17801d395bdcbf20cfb3bb00a"}, -] - -[[package]] -name = "nvidia-curand" -version = "10.4.0.35" -description = "CURAND native runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and (sys_platform == \"linux\" or sys_platform == \"win32\") and python_version >= \"3.10\"" -files = [ - {file = "nvidia_curand-10.4.0.35-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:133df5a7509c3e292aaa2b477afd0194f06ce4ea24d714d616ff36439cee349a"}, - {file = "nvidia_curand-10.4.0.35-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:1aee33a5da6e1db083fe2b90082def8915f30f3248d5896bcec36a579d941bfc"}, - {file = "nvidia_curand-10.4.0.35-py3-none-win_amd64.whl", hash = "sha256:65b1710aa6961d326b411e314b374290904c5ddf41dc3f766ebc3f1d7d4ca69f"}, -] - -[[package]] -name = "nvidia-curand-cu12" -version = "10.3.9.90" -description = "CURAND native runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_curand_cu12-10.3.9.90-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:dfab99248034673b779bc6decafdc3404a8a6f502462201f2f31f11354204acd"}, - {file = "nvidia_curand_cu12-10.3.9.90-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:b32331d4f4df5d6eefa0554c565b626c7216f87a06a4f56fab27c3b68a830ec9"}, - {file = "nvidia_curand_cu12-10.3.9.90-py3-none-win_amd64.whl", hash = "sha256:f149a8ca457277da854f89cf282d6ef43176861926c7ac85b2a0fbd237c587ec"}, -] - -[[package]] -name = "nvidia-cusolver" -version = "12.0.4.66" -description = "CUDA solver native runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and (sys_platform == \"linux\" or sys_platform == \"win32\") and python_version >= \"3.10\"" -files = [ - {file = "nvidia_cusolver-12.0.4.66-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:02c2457eaa9e39de20f880f4bd8820e6a1cfb9f9a34f820eb12a155aa5bc92d2"}, - {file = "nvidia_cusolver-12.0.4.66-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:0a759da5dea5c0ea10fd307de75cdeb59e7ea4fcb8add0924859b944babf1112"}, - {file = "nvidia_cusolver-12.0.4.66-py3-none-win_amd64.whl", hash = "sha256:16515bd33a8e76bb54d024cfa068fa68d30e80fc34b9e1090813ea9362e0cb65"}, -] - -[package.dependencies] -nvidia-cublas = "*" -nvidia-cusparse = "*" -nvidia-nvjitlink = "*" - -[[package]] -name = "nvidia-cusolver-cu12" -version = "11.7.3.90" -description = "CUDA solver native runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_cusolver_cu12-11.7.3.90-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:db9ed69dbef9715071232caa9b69c52ac7de3a95773c2db65bdba85916e4e5c0"}, - {file = "nvidia_cusolver_cu12-11.7.3.90-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:4376c11ad263152bd50ea295c05370360776f8c3427b30991df774f9fb26c450"}, - {file = "nvidia_cusolver_cu12-11.7.3.90-py3-none-win_amd64.whl", hash = "sha256:4a550db115fcabc4d495eb7d39ac8b58d4ab5d8e63274d3754df1c0ad6a22d34"}, -] - -[package.dependencies] -nvidia-cublas-cu12 = "*" -nvidia-cusparse-cu12 = "*" -nvidia-nvjitlink-cu12 = "*" - -[[package]] -name = "nvidia-cusparse" -version = "12.6.3.3" -description = "CUSPARSE native runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and (sys_platform == \"linux\" or sys_platform == \"win32\") and python_version >= \"3.10\"" -files = [ - {file = "nvidia_cusparse-12.6.3.3-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:80bcc4662f23f1054ee334a15c72b8940402975e0eab63178fc7e670aa59472c"}, - {file = "nvidia_cusparse-12.6.3.3-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2b3c89c88d01ee0e477cb7f82ef60a11a4bcd57b6b87c33f789350b59759360b"}, - {file = "nvidia_cusparse-12.6.3.3-py3-none-win_amd64.whl", hash = "sha256:cbcf42feb737bd7ec15b4c0a63e62351886bd3f975027b8815d7f720a2b5ea79"}, -] - -[package.dependencies] -nvidia-nvjitlink = "*" - -[[package]] -name = "nvidia-cusparse-cu12" -version = "12.5.8.93" -description = "CUSPARSE native runtime libraries" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_cusparse_cu12-12.5.8.93-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9b6c161cb130be1a07a27ea6923df8141f3c295852f4b260c65f18f3e0a091dc"}, - {file = "nvidia_cusparse_cu12-12.5.8.93-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1ec05d76bbbd8b61b06a80e1eaf8cf4959c3d4ce8e711b65ebd0443bb0ebb13b"}, - {file = "nvidia_cusparse_cu12-12.5.8.93-py3-none-win_amd64.whl", hash = "sha256:9a33604331cb2cac199f2e7f5104dfbb8a5a898c367a53dfda9ff2acb6b6b4dd"}, -] - -[package.dependencies] -nvidia-nvjitlink-cu12 = "*" - -[[package]] -name = "nvidia-cusparselt-cu12" -version = "0.7.1" -description = "NVIDIA cuSPARSELt" -optional = true -python-versions = "*" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_cusparselt_cu12-0.7.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:8878dce784d0fac90131b6817b607e803c36e629ba34dc5b433471382196b6a5"}, - {file = "nvidia_cusparselt_cu12-0.7.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:f1bb701d6b930d5a7cea44c19ceb973311500847f81b634d802b7b539dc55623"}, - {file = "nvidia_cusparselt_cu12-0.7.1-py3-none-win_amd64.whl", hash = "sha256:f67fbb5831940ec829c9117b7f33807db9f9678dc2a617fbe781cac17b4e1075"}, -] - -[[package]] -name = "nvidia-cusparselt-cu13" -version = "0.8.0" -description = "NVIDIA cuSPARSELt" -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and python_version >= \"3.10\"" -files = [ - {file = "nvidia_cusparselt_cu13-0.8.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:400c6ed1cf6780fc6efedd64ec9f1345871767e6a1a0a552a1ea0578117ea77c"}, - {file = "nvidia_cusparselt_cu13-0.8.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:25e30a8a7323935d4ad0340b95a0b69926eee755767e8e0b1cf8dd85b197d3fd"}, - {file = "nvidia_cusparselt_cu13-0.8.0-py3-none-win_amd64.whl", hash = "sha256:e80212ed7b1afc97102fbb2b5c82487aa73f6a0edfa6d26c5a152593e520bb8f"}, -] - -[[package]] -name = "nvidia-nccl-cu12" -version = "2.27.3" -description = "NVIDIA Collective Communication Library (NCCL) Runtime" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_nccl_cu12-2.27.3-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9ddf1a245abc36c550870f26d537a9b6087fb2e2e3d6e0ef03374c6fd19d984f"}, - {file = "nvidia_nccl_cu12-2.27.3-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:adf27ccf4238253e0b826bce3ff5fa532d65fc42322c8bfdfaf28024c0fbe039"}, -] - -[[package]] -name = "nvidia-nccl-cu13" -version = "2.28.9" -description = "NVIDIA Collective Communication Library (NCCL) Runtime" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and python_version >= \"3.10\"" -files = [ - {file = "nvidia_nccl_cu13-2.28.9-py3-none-manylinux_2_18_aarch64.whl", hash = "sha256:01c873ba1626b54caa12272ed228dc5b2781545e0ae8ba3f432a8ef1c6d78643"}, - {file = "nvidia_nccl_cu13-2.28.9-py3-none-manylinux_2_18_x86_64.whl", hash = "sha256:e4553a30f34195f3fa1da02a6da3d6337d28f2003943aa0a3d247bbc25fefc42"}, -] - -[[package]] -name = "nvidia-nvjitlink" -version = "13.0.88" -description = "Nvidia JIT LTO Library" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and (sys_platform == \"linux\" or sys_platform == \"win32\") and python_version >= \"3.10\"" -files = [ - {file = "nvidia_nvjitlink-13.0.88-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:13a74f429e23b921c1109976abefacc69835f2f433ebd323d3946e11d804e47b"}, - {file = "nvidia_nvjitlink-13.0.88-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e931536ccc7d467a98ba1d8b89ff7fa7f1fa3b13f2b0069118cd7f47bff07d0c"}, - {file = "nvidia_nvjitlink-13.0.88-py3-none-win_amd64.whl", hash = "sha256:634e96e3da9ef845ae744097a1f289238ecf946ce0b82e93cdce14b9782e682f"}, -] - -[[package]] -name = "nvidia-nvjitlink-cu12" -version = "12.8.93" -description = "Nvidia JIT LTO Library" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_nvjitlink_cu12-12.8.93-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:81ff63371a7ebd6e6451970684f916be2eab07321b73c9d244dc2b4da7f73b88"}, - {file = "nvidia_nvjitlink_cu12-12.8.93-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:adccd7161ace7261e01bb91e44e88da350895c270d23f744f0820c818b7229e7"}, - {file = "nvidia_nvjitlink_cu12-12.8.93-py3-none-win_amd64.whl", hash = "sha256:bd93fbeeee850917903583587f4fc3a4eafa022e34572251368238ab5e6bd67f"}, -] - -[[package]] -name = "nvidia-nvshmem-cu13" -version = "3.4.5" -description = "NVSHMEM creates a global address space that provides efficient and scalable communication for NVIDIA GPU clusters." -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and python_version >= \"3.10\"" -files = [ - {file = "nvidia_nvshmem_cu13-3.4.5-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6dc2a197f38e5d0376ad52cd1a2a3617d3cdc150fd5966f4aee9bcebb1d68fe9"}, - {file = "nvidia_nvshmem_cu13-3.4.5-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:290f0a2ee94c9f3687a02502f3b9299a9f9fe826e6d0287ee18482e78d495b80"}, -] - -[[package]] -name = "nvidia-nvtx" -version = "13.0.85" -description = "NVIDIA Tools Extension" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and (sys_platform == \"linux\" or sys_platform == \"win32\") and python_version >= \"3.10\"" -files = [ - {file = "nvidia_nvtx-13.0.85-py3-none-manylinux1_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4936d1d6780fbe68db454f5e72a42ff64d1fd6397df9f363ae786930fd5c1cd4"}, - {file = "nvidia_nvtx-13.0.85-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cb7780edb6b14107373c835bf8b72e7a178bac7367e23da7acb108f973f157a6"}, - {file = "nvidia_nvtx-13.0.85-py3-none-win_amd64.whl", hash = "sha256:d66ea44254dd3c6eacc300047af6e1288d2269dd072b417e0adffbf479e18519"}, -] - -[[package]] -name = "nvidia-nvtx-cu12" -version = "12.8.90" -description = "NVIDIA Tools Extension" -optional = true -python-versions = ">=3" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "nvidia_nvtx_cu12-12.8.90-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d7ad891da111ebafbf7e015d34879f7112832fc239ff0d7d776b6cb685274615"}, - {file = "nvidia_nvtx_cu12-12.8.90-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5b17e2001cc0d751a5bc2c6ec6d26ad95913324a4adb86788c944f8ce9ba441f"}, - {file = "nvidia_nvtx_cu12-12.8.90-py3-none-win_amd64.whl", hash = "sha256:619c8304aedc69f02ea82dd244541a83c3d9d40993381b3b590f1adaed3db41e"}, -] - -[[package]] -name = "oauthlib" -version = "3.2.2" -description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, - {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, -] - -[package.extras] -rsa = ["cryptography (>=3.0.0)"] -signals = ["blinker (>=1.4.0)"] -signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] - -[[package]] -name = "onnxruntime" -version = "1.18.1" -description = "ONNX Runtime is a runtime accelerator for Machine Learning models" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "onnxruntime-1.18.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:29ef7683312393d4ba04252f1b287d964bd67d5e6048b94d2da3643986c74d80"}, - {file = "onnxruntime-1.18.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fc706eb1df06ddf55776e15a30519fb15dda7697f987a2bbda4962845e3cec05"}, - {file = "onnxruntime-1.18.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7de69f5ced2a263531923fa68bbec52a56e793b802fcd81a03487b5e292bc3a"}, - {file = "onnxruntime-1.18.1-cp310-cp310-win32.whl", hash = "sha256:221e5b16173926e6c7de2cd437764492aa12b6811f45abd37024e7cf2ae5d7e3"}, - {file = "onnxruntime-1.18.1-cp310-cp310-win_amd64.whl", hash = "sha256:75211b619275199c861ee94d317243b8a0fcde6032e5a80e1aa9ded8ab4c6060"}, - {file = "onnxruntime-1.18.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:f26582882f2dc581b809cfa41a125ba71ad9e715738ec6402418df356969774a"}, - {file = "onnxruntime-1.18.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef36f3a8b768506d02be349ac303fd95d92813ba3ba70304d40c3cd5c25d6a4c"}, - {file = "onnxruntime-1.18.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:170e711393e0618efa8ed27b59b9de0ee2383bd2a1f93622a97006a5ad48e434"}, - {file = "onnxruntime-1.18.1-cp311-cp311-win32.whl", hash = "sha256:9b6a33419b6949ea34e0dc009bc4470e550155b6da644571ecace4b198b0d88f"}, - {file = "onnxruntime-1.18.1-cp311-cp311-win_amd64.whl", hash = "sha256:5c1380a9f1b7788da742c759b6a02ba771fe1ce620519b2b07309decbd1a2fe1"}, - {file = "onnxruntime-1.18.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:31bd57a55e3f983b598675dfc7e5d6f0877b70ec9864b3cc3c3e1923d0a01919"}, - {file = "onnxruntime-1.18.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9e03c4ba9f734500691a4d7d5b381cd71ee2f3ce80a1154ac8f7aed99d1ecaa"}, - {file = "onnxruntime-1.18.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:781aa9873640f5df24524f96f6070b8c550c66cb6af35710fd9f92a20b4bfbf6"}, - {file = "onnxruntime-1.18.1-cp312-cp312-win32.whl", hash = "sha256:3a2d9ab6254ca62adbb448222e630dc6883210f718065063518c8f93a32432be"}, - {file = "onnxruntime-1.18.1-cp312-cp312-win_amd64.whl", hash = "sha256:ad93c560b1c38c27c0275ffd15cd7f45b3ad3fc96653c09ce2931179982ff204"}, - {file = "onnxruntime-1.18.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:3b55dc9d3c67626388958a3eb7ad87eb7c70f75cb0f7ff4908d27b8b42f2475c"}, - {file = "onnxruntime-1.18.1-cp38-cp38-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f80dbcfb6763cc0177a31168b29b4bd7662545b99a19e211de8c734b657e0669"}, - {file = "onnxruntime-1.18.1-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f1ff2c61a16d6c8631796c54139bafea41ee7736077a0fc64ee8ae59432f5c58"}, - {file = "onnxruntime-1.18.1-cp38-cp38-win32.whl", hash = "sha256:219855bd272fe0c667b850bf1a1a5a02499269a70d59c48e6f27f9c8bcb25d02"}, - {file = "onnxruntime-1.18.1-cp38-cp38-win_amd64.whl", hash = "sha256:afdf16aa607eb9a2c60d5ca2d5abf9f448e90c345b6b94c3ed14f4fb7e6a2d07"}, - {file = "onnxruntime-1.18.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:128df253ade673e60cea0955ec9d0e89617443a6d9ce47c2d79eb3f72a3be3de"}, - {file = "onnxruntime-1.18.1-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9839491e77e5c5a175cab3621e184d5a88925ee297ff4c311b68897197f4cde9"}, - {file = "onnxruntime-1.18.1-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad3187c1faff3ac15f7f0e7373ef4788c582cafa655a80fdbb33eaec88976c66"}, - {file = "onnxruntime-1.18.1-cp39-cp39-win32.whl", hash = "sha256:34657c78aa4e0b5145f9188b550ded3af626651b15017bf43d280d7e23dbf195"}, - {file = "onnxruntime-1.18.1-cp39-cp39-win_amd64.whl", hash = "sha256:9c14fd97c3ddfa97da5feef595e2c73f14c2d0ec1d4ecbea99c8d96603c89589"}, -] - -[package.dependencies] -coloredlogs = "*" -flatbuffers = "*" -numpy = ">=1.21.6,<2.0" -packaging = "*" -protobuf = "*" -sympy = "*" - -[[package]] -name = "openai" -version = "1.51.0" -description = "The official Python library for the openai API" -optional = false -python-versions = ">=3.7.1" -groups = ["main"] -files = [ - {file = "openai-1.51.0-py3-none-any.whl", hash = "sha256:d9affafb7e51e5a27dce78589d4964ce4d6f6d560307265933a94b2e3f3c5d2c"}, - {file = "openai-1.51.0.tar.gz", hash = "sha256:8dc4f9d75ccdd5466fc8c99a952186eddceb9fd6ba694044773f3736a847149d"}, -] - -[package.dependencies] -anyio = ">=3.5.0,<5" -distro = ">=1.7.0,<2" -httpx = ">=0.23.0,<1" -jiter = ">=0.4.0,<1" -pydantic = ">=1.9.0,<3" -sniffio = "*" -tqdm = ">4" -typing-extensions = ">=4.11,<5" - -[package.extras] -datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] - -[[package]] -name = "opensearch-py" -version = "2.3.1" -description = "Python client for OpenSearch" -optional = true -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" -groups = ["main"] -markers = "extra == \"opensearch\"" -files = [ - {file = "opensearch-py-2.3.1.tar.gz", hash = "sha256:f82a2e914835f7d645a632777de9a62d0c0de60ffd2f8cdae2ccfa4cfc40a185"}, - {file = "opensearch_py-2.3.1-py2.py3-none-any.whl", hash = "sha256:eafbc5d56a7ca696afba7d77bcda1bbb849050cbf9265d57d8476576cb576395"}, -] - -[package.dependencies] -certifi = ">=2022.12.7" -python-dateutil = "*" -requests = ">=2.4.0,<3.0.0" -six = "*" -urllib3 = ">=1.21.1,<2" - -[package.extras] -async = ["aiohttp (>=3,<4)"] -develop = ["black", "botocore ; python_version >= \"3.6\"", "coverage (<7.0.0)", "jinja2", "mock", "myst-parser", "pytest (>=3.0.0)", "pytest-cov", "pytest-mock (<4.0.0)", "pytz", "pyyaml", "requests (>=2.0.0,<3.0.0)", "sphinx", "sphinx-copybutton", "sphinx-rtd-theme"] -docs = ["myst-parser", "sphinx", "sphinx-copybutton", "sphinx-rtd-theme"] -kerberos = ["requests-kerberos"] - -[[package]] -name = "opentelemetry-api" -version = "1.25.0" -description = "OpenTelemetry Python API" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_api-1.25.0-py3-none-any.whl", hash = "sha256:757fa1aa020a0f8fa139f8959e53dec2051cc26b832e76fa839a6d76ecefd737"}, - {file = "opentelemetry_api-1.25.0.tar.gz", hash = "sha256:77c4985f62f2614e42ce77ee4c9da5fa5f0bc1e1821085e9a47533a9323ae869"}, -] - -[package.dependencies] -deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<=7.1" - -[[package]] -name = "opentelemetry-exporter-otlp-proto-common" -version = "1.25.0" -description = "OpenTelemetry Protobuf encoding" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_exporter_otlp_proto_common-1.25.0-py3-none-any.whl", hash = "sha256:15637b7d580c2675f70246563363775b4e6de947871e01d0f4e3881d1848d693"}, - {file = "opentelemetry_exporter_otlp_proto_common-1.25.0.tar.gz", hash = "sha256:c93f4e30da4eee02bacd1e004eb82ce4da143a2f8e15b987a9f603e0a85407d3"}, -] - -[package.dependencies] -opentelemetry-proto = "1.25.0" - -[[package]] -name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.25.0" -description = "OpenTelemetry Collector Protobuf over gRPC Exporter" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_exporter_otlp_proto_grpc-1.25.0-py3-none-any.whl", hash = "sha256:3131028f0c0a155a64c430ca600fd658e8e37043cb13209f0109db5c1a3e4eb4"}, - {file = "opentelemetry_exporter_otlp_proto_grpc-1.25.0.tar.gz", hash = "sha256:c0b1661415acec5af87625587efa1ccab68b873745ca0ee96b69bb1042087eac"}, -] - -[package.dependencies] -deprecated = ">=1.2.6" -googleapis-common-protos = ">=1.52,<2.0" -grpcio = ">=1.0.0,<2.0.0" -opentelemetry-api = ">=1.15,<2.0" -opentelemetry-exporter-otlp-proto-common = "1.25.0" -opentelemetry-proto = "1.25.0" -opentelemetry-sdk = ">=1.25.0,<1.26.0" - -[[package]] -name = "opentelemetry-instrumentation" -version = "0.46b0" -description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_instrumentation-0.46b0-py3-none-any.whl", hash = "sha256:89cd721b9c18c014ca848ccd11181e6b3fd3f6c7669e35d59c48dc527408c18b"}, - {file = "opentelemetry_instrumentation-0.46b0.tar.gz", hash = "sha256:974e0888fb2a1e01c38fbacc9483d024bb1132aad92d6d24e2e5543887a7adda"}, -] - -[package.dependencies] -opentelemetry-api = ">=1.4,<2.0" -setuptools = ">=16.0" -wrapt = ">=1.0.0,<2.0.0" - -[[package]] -name = "opentelemetry-instrumentation-asgi" -version = "0.46b0" -description = "ASGI instrumentation for OpenTelemetry" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_instrumentation_asgi-0.46b0-py3-none-any.whl", hash = "sha256:f13c55c852689573057837a9500aeeffc010c4ba59933c322e8f866573374759"}, - {file = "opentelemetry_instrumentation_asgi-0.46b0.tar.gz", hash = "sha256:02559f30cf4b7e2a737ab17eb52aa0779bcf4cc06573064f3e2cb4dcc7d3040a"}, -] - -[package.dependencies] -asgiref = ">=3.0,<4.0" -opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.46b0" -opentelemetry-semantic-conventions = "0.46b0" -opentelemetry-util-http = "0.46b0" - -[package.extras] -instruments = ["asgiref (>=3.0,<4.0)"] - -[[package]] -name = "opentelemetry-instrumentation-fastapi" -version = "0.46b0" -description = "OpenTelemetry FastAPI Instrumentation" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_instrumentation_fastapi-0.46b0-py3-none-any.whl", hash = "sha256:e0f5d150c6c36833dd011f0e6ef5ede6d7406c1aed0c7c98b2d3b38a018d1b33"}, - {file = "opentelemetry_instrumentation_fastapi-0.46b0.tar.gz", hash = "sha256:928a883a36fc89f9702f15edce43d1a7104da93d740281e32d50ffd03dbb4365"}, -] - -[package.dependencies] -opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.46b0" -opentelemetry-instrumentation-asgi = "0.46b0" -opentelemetry-semantic-conventions = "0.46b0" -opentelemetry-util-http = "0.46b0" - -[package.extras] -instruments = ["fastapi (>=0.58,<1.0)"] - -[[package]] -name = "opentelemetry-proto" -version = "1.25.0" -description = "OpenTelemetry Python Proto" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_proto-1.25.0-py3-none-any.whl", hash = "sha256:f07e3341c78d835d9b86665903b199893befa5e98866f63d22b00d0b7ca4972f"}, - {file = "opentelemetry_proto-1.25.0.tar.gz", hash = "sha256:35b6ef9dc4a9f7853ecc5006738ad40443701e52c26099e197895cbda8b815a3"}, -] - -[package.dependencies] -protobuf = ">=3.19,<5.0" - -[[package]] -name = "opentelemetry-sdk" -version = "1.25.0" -description = "OpenTelemetry Python SDK" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_sdk-1.25.0-py3-none-any.whl", hash = "sha256:d97ff7ec4b351692e9d5a15af570c693b8715ad78b8aafbec5c7100fe966b4c9"}, - {file = "opentelemetry_sdk-1.25.0.tar.gz", hash = "sha256:ce7fc319c57707ef5bf8b74fb9f8ebdb8bfafbe11898410e0d2a761d08a98ec7"}, -] - -[package.dependencies] -opentelemetry-api = "1.25.0" -opentelemetry-semantic-conventions = "0.46b0" -typing-extensions = ">=3.7.4" - -[[package]] -name = "opentelemetry-semantic-conventions" -version = "0.46b0" -description = "OpenTelemetry Semantic Conventions" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_semantic_conventions-0.46b0-py3-none-any.whl", hash = "sha256:6daef4ef9fa51d51855d9f8e0ccd3a1bd59e0e545abe99ac6203804e36ab3e07"}, - {file = "opentelemetry_semantic_conventions-0.46b0.tar.gz", hash = "sha256:fbc982ecbb6a6e90869b15c1673be90bd18c8a56ff1cffc0864e38e2edffaefa"}, -] - -[package.dependencies] -opentelemetry-api = "1.25.0" - -[[package]] -name = "opentelemetry-util-http" -version = "0.46b0" -description = "Web util for OpenTelemetry" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_util_http-0.46b0-py3-none-any.whl", hash = "sha256:8dc1949ce63caef08db84ae977fdc1848fe6dc38e6bbaad0ae3e6ecd0d451629"}, - {file = "opentelemetry_util_http-0.46b0.tar.gz", hash = "sha256:03b6e222642f9c7eae58d9132343e045b50aca9761fcb53709bd2b663571fdf6"}, -] - -[[package]] -name = "orjson" -version = "3.10.6" -description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "orjson-3.10.6-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:fb0ee33124db6eaa517d00890fc1a55c3bfe1cf78ba4a8899d71a06f2d6ff5c7"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c1c4b53b24a4c06547ce43e5fee6ec4e0d8fe2d597f4647fc033fd205707365"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eadc8fd310edb4bdbd333374f2c8fec6794bbbae99b592f448d8214a5e4050c0"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61272a5aec2b2661f4fa2b37c907ce9701e821b2c1285d5c3ab0207ebd358d38"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57985ee7e91d6214c837936dc1608f40f330a6b88bb13f5a57ce5257807da143"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:633a3b31d9d7c9f02d49c4ab4d0a86065c4a6f6adc297d63d272e043472acab5"}, - {file = "orjson-3.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1c680b269d33ec444afe2bdc647c9eb73166fa47a16d9a75ee56a374f4a45f43"}, - {file = "orjson-3.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f759503a97a6ace19e55461395ab0d618b5a117e8d0fbb20e70cfd68a47327f2"}, - {file = "orjson-3.10.6-cp310-none-win32.whl", hash = "sha256:95a0cce17f969fb5391762e5719575217bd10ac5a189d1979442ee54456393f3"}, - {file = "orjson-3.10.6-cp310-none-win_amd64.whl", hash = "sha256:df25d9271270ba2133cc88ee83c318372bdc0f2cd6f32e7a450809a111efc45c"}, - {file = "orjson-3.10.6-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b1ec490e10d2a77c345def52599311849fc063ae0e67cf4f84528073152bb2ba"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d43d3feb8f19d07e9f01e5b9be4f28801cf7c60d0fa0d279951b18fae1932b"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3045267e98fe749408eee1593a142e02357c5c99be0802185ef2170086a863"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c27bc6a28ae95923350ab382c57113abd38f3928af3c80be6f2ba7eb8d8db0b0"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d27456491ca79532d11e507cadca37fb8c9324a3976294f68fb1eff2dc6ced5a"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05ac3d3916023745aa3b3b388e91b9166be1ca02b7c7e41045da6d12985685f0"}, - {file = "orjson-3.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1335d4ef59ab85cab66fe73fd7a4e881c298ee7f63ede918b7faa1b27cbe5212"}, - {file = "orjson-3.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4bbc6d0af24c1575edc79994c20e1b29e6fb3c6a570371306db0993ecf144dc5"}, - {file = "orjson-3.10.6-cp311-none-win32.whl", hash = "sha256:450e39ab1f7694465060a0550b3f6d328d20297bf2e06aa947b97c21e5241fbd"}, - {file = "orjson-3.10.6-cp311-none-win_amd64.whl", hash = "sha256:227df19441372610b20e05bdb906e1742ec2ad7a66ac8350dcfd29a63014a83b"}, - {file = "orjson-3.10.6-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ea2977b21f8d5d9b758bb3f344a75e55ca78e3ff85595d248eee813ae23ecdfb"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b6f3d167d13a16ed263b52dbfedff52c962bfd3d270b46b7518365bcc2121eed"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f710f346e4c44a4e8bdf23daa974faede58f83334289df80bc9cd12fe82573c7"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7275664f84e027dcb1ad5200b8b18373e9c669b2a9ec33d410c40f5ccf4b257e"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0943e4c701196b23c240b3d10ed8ecd674f03089198cf503105b474a4f77f21f"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:446dee5a491b5bc7d8f825d80d9637e7af43f86a331207b9c9610e2f93fee22a"}, - {file = "orjson-3.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:64c81456d2a050d380786413786b057983892db105516639cb5d3ee3c7fd5148"}, - {file = "orjson-3.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:960db0e31c4e52fa0fc3ecbaea5b2d3b58f379e32a95ae6b0ebeaa25b93dfd34"}, - {file = "orjson-3.10.6-cp312-none-win32.whl", hash = "sha256:a6ea7afb5b30b2317e0bee03c8d34c8181bc5a36f2afd4d0952f378972c4efd5"}, - {file = "orjson-3.10.6-cp312-none-win_amd64.whl", hash = "sha256:874ce88264b7e655dde4aeaacdc8fd772a7962faadfb41abe63e2a4861abc3dc"}, - {file = "orjson-3.10.6-cp313-none-win32.whl", hash = "sha256:efdf2c5cde290ae6b83095f03119bdc00303d7a03b42b16c54517baa3c4ca3d0"}, - {file = "orjson-3.10.6-cp313-none-win_amd64.whl", hash = "sha256:8e190fe7888e2e4392f52cafb9626113ba135ef53aacc65cd13109eb9746c43e"}, - {file = "orjson-3.10.6-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:66680eae4c4e7fc193d91cfc1353ad6d01b4801ae9b5314f17e11ba55e934183"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:caff75b425db5ef8e8f23af93c80f072f97b4fb3afd4af44482905c9f588da28"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3722fddb821b6036fd2a3c814f6bd9b57a89dc6337b9924ecd614ebce3271394"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2c116072a8533f2fec435fde4d134610f806bdac20188c7bd2081f3e9e0133f"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6eeb13218c8cf34c61912e9df2de2853f1d009de0e46ea09ccdf3d757896af0a"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:965a916373382674e323c957d560b953d81d7a8603fbeee26f7b8248638bd48b"}, - {file = "orjson-3.10.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:03c95484d53ed8e479cade8628c9cea00fd9d67f5554764a1110e0d5aa2de96e"}, - {file = "orjson-3.10.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:e060748a04cccf1e0a6f2358dffea9c080b849a4a68c28b1b907f272b5127e9b"}, - {file = "orjson-3.10.6-cp38-none-win32.whl", hash = "sha256:738dbe3ef909c4b019d69afc19caf6b5ed0e2f1c786b5d6215fbb7539246e4c6"}, - {file = "orjson-3.10.6-cp38-none-win_amd64.whl", hash = "sha256:d40f839dddf6a7d77114fe6b8a70218556408c71d4d6e29413bb5f150a692ff7"}, - {file = "orjson-3.10.6-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:697a35a083c4f834807a6232b3e62c8b280f7a44ad0b759fd4dce748951e70db"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd502f96bf5ea9a61cbc0b2b5900d0dd68aa0da197179042bdd2be67e51a1e4b"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f215789fb1667cdc874c1b8af6a84dc939fd802bf293a8334fce185c79cd359b"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2debd8ddce948a8c0938c8c93ade191d2f4ba4649a54302a7da905a81f00b56"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5410111d7b6681d4b0d65e0f58a13be588d01b473822483f77f513c7f93bd3b2"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb1f28a137337fdc18384079fa5726810681055b32b92253fa15ae5656e1dddb"}, - {file = "orjson-3.10.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bf2fbbce5fe7cd1aa177ea3eab2b8e6a6bc6e8592e4279ed3db2d62e57c0e1b2"}, - {file = "orjson-3.10.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:79b9b9e33bd4c517445a62b90ca0cc279b0f1f3970655c3df9e608bc3f91741a"}, - {file = "orjson-3.10.6-cp39-none-win32.whl", hash = "sha256:30b0a09a2014e621b1adf66a4f705f0809358350a757508ee80209b2d8dae219"}, - {file = "orjson-3.10.6-cp39-none-win_amd64.whl", hash = "sha256:49e3bc615652617d463069f91b867a4458114c5b104e13b7ae6872e5f79d0844"}, - {file = "orjson-3.10.6.tar.gz", hash = "sha256:e54b63d0a7c6c54a5f5f726bc93a2078111ef060fec4ecbf34c5db800ca3b3a7"}, -] - -[[package]] -name = "overrides" -version = "7.7.0" -description = "A decorator to automatically detect mismatch when overriding a method." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49"}, - {file = "overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a"}, -] - -[[package]] -name = "packaging" -version = "24.1" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, -] - -[[package]] -name = "pandas" -version = "2.2.2" -description = "Powerful data structures for data analysis, time series, and statistics" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, - {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"}, - {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"}, - {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"}, - {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"}, - {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99"}, - {file = "pandas-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772"}, - {file = "pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288"}, - {file = "pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151"}, - {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b"}, - {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee"}, - {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db"}, - {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"}, - {file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"}, - {file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"}, - {file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"}, - {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"}, - {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"}, - {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"}, - {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"}, - {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"}, - {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"}, - {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"}, - {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"}, - {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"}, - {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"}, - {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57"}, - {file = "pandas-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4"}, - {file = "pandas-2.2.2.tar.gz", hash = "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54"}, -] - -[package.dependencies] -numpy = [ - {version = ">=1.23.2", markers = "python_version == \"3.11\""}, - {version = ">=1.22.4", markers = "python_version < \"3.11\""}, - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, -] -python-dateutil = ">=2.8.2" -pytz = ">=2020.1" -tzdata = ">=2022.7" - -[package.extras] -all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] -aws = ["s3fs (>=2022.11.0)"] -clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] -compression = ["zstandard (>=0.19.0)"] -computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] -consortium-standard = ["dataframe-api-compat (>=0.1.7)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] -feather = ["pyarrow (>=10.0.1)"] -fss = ["fsspec (>=2022.11.0)"] -gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] -hdf5 = ["tables (>=3.8.0)"] -html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] -mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] -parquet = ["pyarrow (>=10.0.1)"] -performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] -plot = ["matplotlib (>=3.6.3)"] -postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] -pyarrow = ["pyarrow (>=10.0.1)"] -spss = ["pyreadstat (>=1.2.0)"] -sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.9.2)"] - -[[package]] -name = "parameterized" -version = "0.9.0" -description = "Parameterized testing with any Python test framework" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "parameterized-0.9.0-py2.py3-none-any.whl", hash = "sha256:4e0758e3d41bea3bbd05ec14fc2c24736723f243b28d702081aef438c9372b1b"}, - {file = "parameterized-0.9.0.tar.gz", hash = "sha256:7fc905272cefa4f364c1a3429cbbe9c0f98b793988efb5bf90aac80f08db09b1"}, -] - -[package.extras] -dev = ["jinja2"] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "pillow" -version = "10.4.0" -description = "Python Imaging Library (Fork)" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"opensource\" or extra == \"together\"" -files = [ - {file = "pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e"}, - {file = "pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc"}, - {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e"}, - {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46"}, - {file = "pillow-10.4.0-cp310-cp310-win32.whl", hash = "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984"}, - {file = "pillow-10.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141"}, - {file = "pillow-10.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1"}, - {file = "pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c"}, - {file = "pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319"}, - {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d"}, - {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696"}, - {file = "pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496"}, - {file = "pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91"}, - {file = "pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22"}, - {file = "pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94"}, - {file = "pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a"}, - {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b"}, - {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9"}, - {file = "pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42"}, - {file = "pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a"}, - {file = "pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9"}, - {file = "pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3"}, - {file = "pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc"}, - {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a"}, - {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309"}, - {file = "pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060"}, - {file = "pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea"}, - {file = "pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d"}, - {file = "pillow-10.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736"}, - {file = "pillow-10.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd"}, - {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84"}, - {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0"}, - {file = "pillow-10.4.0-cp38-cp38-win32.whl", hash = "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e"}, - {file = "pillow-10.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab"}, - {file = "pillow-10.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d"}, - {file = "pillow-10.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c"}, - {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1"}, - {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df"}, - {file = "pillow-10.4.0-cp39-cp39-win32.whl", hash = "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef"}, - {file = "pillow-10.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5"}, - {file = "pillow-10.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3"}, - {file = "pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06"}, -] - -[package.extras] -docs = ["furo", "olefile", "sphinx (>=7.3)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] -fpx = ["olefile"] -mic = ["olefile"] -tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] -typing = ["typing-extensions ; python_version < \"3.10\""] -xmp = ["defusedxml"] - -[[package]] -name = "platformdirs" -version = "4.2.2" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, -] - -[package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] - -[[package]] -name = "pluggy" -version = "1.5.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "portalocker" -version = "2.10.0" -description = "Wraps the portalocker recipe for easy usage" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "portalocker-2.10.0-py3-none-any.whl", hash = "sha256:48944147b2cd42520549bc1bb8fe44e220296e56f7c3d551bc6ecce69d9b0de1"}, - {file = "portalocker-2.10.0.tar.gz", hash = "sha256:49de8bc0a2f68ca98bf9e219c81a3e6b27097c7bf505a87c5a112ce1aaeb9b81"}, -] - -[package.dependencies] -pywin32 = {version = ">=226", markers = "platform_system == \"Windows\""} - -[package.extras] -docs = ["sphinx (>=1.7.1)"] -redis = ["redis"] -tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "pytest-timeout (>=2.1.0)", "redis", "sphinx (>=6.0.0)", "types-redis"] - -[[package]] -name = "posthog" -version = "3.5.0" -description = "Integrate PostHog into any python application." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "posthog-3.5.0-py2.py3-none-any.whl", hash = "sha256:3c672be7ba6f95d555ea207d4486c171d06657eb34b3ce25eb043bfe7b6b5b76"}, - {file = "posthog-3.5.0.tar.gz", hash = "sha256:8f7e3b2c6e8714d0c0c542a2109b83a7549f63b7113a133ab2763a89245ef2ef"}, -] - -[package.dependencies] -backoff = ">=1.10.0" -monotonic = ">=1.5" -python-dateutil = ">2.1" -requests = ">=2.7,<3.0" -six = ">=1.5" - -[package.extras] -dev = ["black", "flake8", "flake8-print", "isort", "pre-commit"] -sentry = ["django", "sentry-sdk"] -test = ["coverage", "flake8", "freezegun (==0.3.15)", "mock (>=2.0.0)", "pylint", "pytest", "pytest-timeout"] - -[[package]] -name = "pre-commit" -version = "3.7.1" -description = "A framework for managing and maintaining multi-language pre-commit hooks." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pre_commit-3.7.1-py2.py3-none-any.whl", hash = "sha256:fae36fd1d7ad7d6a5a1c0b0d5adb2ed1a3bda5a21bf6c3e5372073d7a11cd4c5"}, - {file = "pre_commit-3.7.1.tar.gz", hash = "sha256:8ca3ad567bc78a4972a3f1a477e94a79d4597e8140a6e0b651c5e33899c3654a"}, -] - -[package.dependencies] -cfgv = ">=2.0.0" -identify = ">=1.0.0" -nodeenv = ">=0.11.1" -pyyaml = ">=5.1" -virtualenv = ">=20.10.0" - -[[package]] -name = "proto-plus" -version = "1.24.0" -description = "Beautiful, Pythonic protocol buffers." -optional = true -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "proto-plus-1.24.0.tar.gz", hash = "sha256:30b72a5ecafe4406b0d339db35b56c4059064e69227b8c3bda7462397f966445"}, - {file = "proto_plus-1.24.0-py3-none-any.whl", hash = "sha256:402576830425e5f6ce4c2a6702400ac79897dab0b4343821aa5188b0fab81a12"}, -] - -[package.dependencies] -protobuf = ">=3.19.0,<6.0.0.dev0" - -[package.extras] -testing = ["google-api-core (>=1.31.5)"] - -[[package]] -name = "protobuf" -version = "4.25.3" -description = "" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, - {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"}, - {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"}, - {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"}, - {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"}, - {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"}, - {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"}, - {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"}, - {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"}, - {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"}, - {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, -] - -[[package]] -name = "psycopg" -version = "3.2.1" -description = "PostgreSQL database adapter for Python" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"postgres\"" -files = [ - {file = "psycopg-3.2.1-py3-none-any.whl", hash = "sha256:ece385fb413a37db332f97c49208b36cf030ff02b199d7635ed2fbd378724175"}, - {file = "psycopg-3.2.1.tar.gz", hash = "sha256:dc8da6dc8729dacacda3cc2f17d2c9397a70a66cf0d2b69c91065d60d5f00cb7"}, -] - -[package.dependencies] -typing-extensions = ">=4.4" -tzdata = {version = "*", markers = "sys_platform == \"win32\""} - -[package.extras] -binary = ["psycopg-binary (==3.2.1) ; implementation_name != \"pypy\""] -c = ["psycopg-c (==3.2.1) ; implementation_name != \"pypy\""] -dev = ["ast-comments (>=1.1.2)", "black (>=24.1.0)", "codespell (>=2.2)", "dnspython (>=2.1)", "flake8 (>=4.0)", "mypy (>=1.6)", "types-setuptools (>=57.4)", "wheel (>=0.37)"] -docs = ["Sphinx (>=5.0)", "furo (==2022.6.21)", "sphinx-autobuild (>=2021.3.14)", "sphinx-autodoc-typehints (>=1.12)"] -pool = ["psycopg-pool"] -test = ["anyio (>=4.0)", "mypy (>=1.6)", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"] - -[[package]] -name = "psycopg-binary" -version = "3.2.1" -description = "PostgreSQL database adapter for Python -- C optimisation distribution" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"postgres\"" -files = [ - {file = "psycopg_binary-3.2.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:cad2de17804c4cfee8640ae2b279d616bb9e4734ac3c17c13db5e40982bd710d"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:592b27d6c46a40f9eeaaeea7c1fef6f3c60b02c634365eb649b2d880669f149f"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a997efbaadb5e1a294fb5760e2f5643d7b8e4e3fe6cb6f09e6d605fd28e0291"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1d2b6438fb83376f43ebb798bf0ad5e57bc56c03c9c29c85bc15405c8c0ac5a"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b1f087bd84bdcac78bf9f024ebdbfacd07fc0a23ec8191448a50679e2ac4a19e"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:415c3b72ea32119163255c6504085f374e47ae7345f14bc3f0ef1f6e0976a879"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f092114f10f81fb6bae544a0ec027eb720e2d9c74a4fcdaa9dd3899873136935"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:06a7aae34edfe179ddc04da005e083ff6c6b0020000399a2cbf0a7121a8a22ea"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0b018631e5c80ce9bc210b71ea885932f9cca6db131e4df505653d7e3873a938"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f8a509aeaac364fa965454e80cd110fe6d48ba2c80f56c9b8563423f0b5c3cfd"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:413977d18412ff83486eeb5875eb00b185a9391c57febac45b8993bf9c0ff489"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:62b1b7b07e00ee490afb39c0a47d8282a9c2822c7cfed9553a04b0058adf7e7f"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:f8afb07114ea9b924a4a0305ceb15354ccf0ef3c0e14d54b8dbeb03e50182dd7"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40bb515d042f6a345714ec0403df68ccf13f73b05e567837d80c886c7c9d3805"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6418712ba63cebb0c88c050b3997185b0ef54173b36568522d5634ac06153040"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:101472468d59c74bb8565fab603e032803fd533d16be4b2d13da1bab8deb32a3"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa3931f308ab4a479d0ee22dc04bea867a6365cac0172e5ddcba359da043854b"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dc314a47d44fe1a8069b075a64abffad347a3a1d8652fed1bab5d3baea37acb2"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:cc304a46be1e291031148d9d95c12451ffe783ff0cc72f18e2cc7ec43cdb8c68"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6f9e13600647087df5928875559f0eb8f496f53e6278b7da9511b4b3d0aff960"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b140182830c76c74d17eba27df3755a46442ce8d4fb299e7f1cf2f74a87c877b"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:3c838806eeb99af39f934b7999e35f947a8e577997cc892c12b5053a97a9057f"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:7066d3dca196ed0dc6172f9777b2d62e4f138705886be656cccff2d555234d60"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:28ada5f610468c57d8a4a055a8ea915d0085a43d794266c4f3b9d02f4288f4db"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e8213bf50af073b1aa8dc3cff123bfeedac86332a16c1b7274910bc88a847c7"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74d623261655a169bc84a9669890975c229f2fa6e19a7f2d10a77675dcf1a707"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:42781ba94e8842ee98bca5a7d0c44cc9d067500fedca2d6a90fa3609b6d16b42"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33e6669091d09f8ba36e10ce678a6d9916e110446236a9b92346464a3565635e"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b09e8a576a2ac69d695032ee76f31e03b30781828b5dd6d18c6a009e5a3d1c35"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8f28ff0cb9f1defdc4a6f8c958bf6787274247e7dfeca811f6e2f56602695fb1"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4c84fcac8a3a3479ac14673095cc4e1fdba2935499f72c436785ac679bec0d1a"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:950fd666ec9e9fe6a8eeb2b5a8f17301790e518953730ad44d715b59ffdbc67f"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:334046a937bb086c36e2c6889fe327f9f29bfc085d678f70fac0b0618949f674"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:1d6833f607f3fc7b22226a9e121235d3b84c0eda1d3caab174673ef698f63788"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d353e028b8f848b9784450fc2abf149d53a738d451eab3ee4c85703438128b9"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f34e369891f77d0738e5d25727c307d06d5344948771e5379ea29c76c6d84555"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ab58213cc976a1666f66bc1cb2e602315cd753b7981a8e17237ac2a185bd4a1"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0104a72a17aa84b3b7dcab6c84826c595355bf54bb6ea6d284dcb06d99c6801"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:059cbd4e6da2337e17707178fe49464ed01de867dc86c677b30751755ec1dc51"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:73f9c9b984be9c322b5ec1515b12df1ee5896029f5e72d46160eb6517438659c"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:af0469c00f24c4bec18c3d2ede124bf62688d88d1b8a5f3c3edc2f61046fe0d7"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:463d55345f73ff391df8177a185ad57b552915ad33f5cc2b31b930500c068b22"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:302b86f92c0d76e99fe1b5c22c492ae519ce8b98b88d37ef74fda4c9e24c6b46"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:0879b5d76b7d48678d31278242aaf951bc2d69ca4e4d7cef117e4bbf7bfefda9"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f99e59f8a5f4dcd9cbdec445f3d8ac950a492fc0e211032384d6992ed3c17eb7"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84837e99353d16c6980603b362d0f03302d4b06c71672a6651f38df8a482923d"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ce965caf618061817f66c0906f0452aef966c293ae0933d4fa5a16ea6eaf5bb"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78c2007caf3c90f08685c5378e3ceb142bafd5636be7495f7d86ec8a977eaeef"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7a84b5eb194a258116154b2a4ff2962ea60ea52de089508db23a51d3d6b1c7d1"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4a42b8f9ab39affcd5249b45cac763ac3cf12df962b67e23fd15a2ee2932afe5"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:788ffc43d7517c13e624c83e0e553b7b8823c9655e18296566d36a829bfb373f"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:21927f41c4d722ae8eb30d62a6ce732c398eac230509af5ba1749a337f8a63e2"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:921f0c7f39590763d64a619de84d1b142587acc70fd11cbb5ba8fa39786f3073"}, -] - -[[package]] -name = "psycopg-pool" -version = "3.2.2" -description = "Connection Pool for Psycopg" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"postgres\"" -files = [ - {file = "psycopg_pool-3.2.2-py3-none-any.whl", hash = "sha256:273081d0fbfaced4f35e69200c89cb8fbddfe277c38cc86c235b90a2ec2c8153"}, - {file = "psycopg_pool-3.2.2.tar.gz", hash = "sha256:9e22c370045f6d7f2666a5ad1b0caf345f9f1912195b0b25d0d3bcc4f3a7389c"}, -] - -[package.dependencies] -typing-extensions = ">=4.4" - -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -optional = true -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main"] -markers = "extra == \"lancedb\"" -files = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] - -[[package]] -name = "pyarrow" -version = "15.0.0" -description = "Python library for Apache Arrow" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"together\" or extra == \"lancedb\"" -files = [ - {file = "pyarrow-15.0.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:0a524532fd6dd482edaa563b686d754c70417c2f72742a8c990b322d4c03a15d"}, - {file = "pyarrow-15.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:60a6bdb314affa9c2e0d5dddf3d9cbb9ef4a8dddaa68669975287d47ece67642"}, - {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66958fd1771a4d4b754cd385835e66a3ef6b12611e001d4e5edfcef5f30391e2"}, - {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f500956a49aadd907eaa21d4fff75f73954605eaa41f61cb94fb008cf2e00c6"}, - {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6f87d9c4f09e049c2cade559643424da84c43a35068f2a1c4653dc5b1408a929"}, - {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:85239b9f93278e130d86c0e6bb455dcb66fc3fd891398b9d45ace8799a871a1e"}, - {file = "pyarrow-15.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:5b8d43e31ca16aa6e12402fcb1e14352d0d809de70edd185c7650fe80e0769e3"}, - {file = "pyarrow-15.0.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:fa7cd198280dbd0c988df525e50e35b5d16873e2cdae2aaaa6363cdb64e3eec5"}, - {file = "pyarrow-15.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8780b1a29d3c8b21ba6b191305a2a607de2e30dab399776ff0aa09131e266340"}, - {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe0ec198ccc680f6c92723fadcb97b74f07c45ff3fdec9dd765deb04955ccf19"}, - {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:036a7209c235588c2f07477fe75c07e6caced9b7b61bb897c8d4e52c4b5f9555"}, - {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2bd8a0e5296797faf9a3294e9fa2dc67aa7f10ae2207920dbebb785c77e9dbe5"}, - {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:e8ebed6053dbe76883a822d4e8da36860f479d55a762bd9e70d8494aed87113e"}, - {file = "pyarrow-15.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:17d53a9d1b2b5bd7d5e4cd84d018e2a45bc9baaa68f7e6e3ebed45649900ba99"}, - {file = "pyarrow-15.0.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:9950a9c9df24090d3d558b43b97753b8f5867fb8e521f29876aa021c52fda351"}, - {file = "pyarrow-15.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:003d680b5e422d0204e7287bb3fa775b332b3fce2996aa69e9adea23f5c8f970"}, - {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f75fce89dad10c95f4bf590b765e3ae98bcc5ba9f6ce75adb828a334e26a3d40"}, - {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca9cb0039923bec49b4fe23803807e4ef39576a2bec59c32b11296464623dc2"}, - {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:9ed5a78ed29d171d0acc26a305a4b7f83c122d54ff5270810ac23c75813585e4"}, - {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:6eda9e117f0402dfcd3cd6ec9bfee89ac5071c48fc83a84f3075b60efa96747f"}, - {file = "pyarrow-15.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9a3a6180c0e8f2727e6f1b1c87c72d3254cac909e609f35f22532e4115461177"}, - {file = "pyarrow-15.0.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:19a8918045993349b207de72d4576af0191beef03ea655d8bdb13762f0cd6eac"}, - {file = "pyarrow-15.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d0ec076b32bacb6666e8813a22e6e5a7ef1314c8069d4ff345efa6246bc38593"}, - {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5db1769e5d0a77eb92344c7382d6543bea1164cca3704f84aa44e26c67e320fb"}, - {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2617e3bf9df2a00020dd1c1c6dce5cc343d979efe10bc401c0632b0eef6ef5b"}, - {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:d31c1d45060180131caf10f0f698e3a782db333a422038bf7fe01dace18b3a31"}, - {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:c8c287d1d479de8269398b34282e206844abb3208224dbdd7166d580804674b7"}, - {file = "pyarrow-15.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:07eb7f07dc9ecbb8dace0f58f009d3a29ee58682fcdc91337dfeb51ea618a75b"}, - {file = "pyarrow-15.0.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:47af7036f64fce990bb8a5948c04722e4e3ea3e13b1007ef52dfe0aa8f23cf7f"}, - {file = "pyarrow-15.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93768ccfff85cf044c418bfeeafce9a8bb0cee091bd8fd19011aff91e58de540"}, - {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6ee87fd6892700960d90abb7b17a72a5abb3b64ee0fe8db6c782bcc2d0dc0b4"}, - {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:001fca027738c5f6be0b7a3159cc7ba16a5c52486db18160909a0831b063c4e4"}, - {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:d1c48648f64aec09accf44140dccb92f4f94394b8d79976c426a5b79b11d4fa7"}, - {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:972a0141be402bb18e3201448c8ae62958c9c7923dfaa3b3d4530c835ac81aed"}, - {file = "pyarrow-15.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:f01fc5cf49081426429127aa2d427d9d98e1cb94a32cb961d583a70b7c4504e6"}, - {file = "pyarrow-15.0.0.tar.gz", hash = "sha256:876858f549d540898f927eba4ef77cd549ad8d24baa3207cf1b72e5788b50e83"}, -] - -[package.dependencies] -numpy = ">=1.16.6,<2" - -[[package]] -name = "pyasn1" -version = "0.6.0" -description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pyasn1-0.6.0-py2.py3-none-any.whl", hash = "sha256:cca4bb0f2df5504f02f6f8a775b6e416ff9b0b3b16f7ee80b5a3153d9b804473"}, - {file = "pyasn1-0.6.0.tar.gz", hash = "sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c"}, -] - -[[package]] -name = "pyasn1-modules" -version = "0.4.0" -description = "A collection of ASN.1-based protocols modules" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pyasn1_modules-0.4.0-py3-none-any.whl", hash = "sha256:be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b"}, - {file = "pyasn1_modules-0.4.0.tar.gz", hash = "sha256:831dbcea1b177b28c9baddf4c6d1013c24c3accd14a1873fffaa6a2e905f17b6"}, -] - -[package.dependencies] -pyasn1 = ">=0.4.6,<0.7.0" - -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"weaviate\" or platform_python_implementation == \"PyPy\"" -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - -[[package]] -name = "pydantic" -version = "2.8.2" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"}, - {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"}, -] - -[package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.20.1" -typing-extensions = [ - {version = ">=4.6.1", markers = "python_version < \"3.13\""}, - {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, -] - -[package.extras] -email = ["email-validator (>=2.0.0)"] - -[[package]] -name = "pydantic-core" -version = "2.20.1" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"}, - {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"}, - {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"}, - {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"}, - {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"}, - {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"}, - {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"}, - {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"}, - {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"}, - {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"}, - {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"}, - {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"}, - {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"}, - {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pydantic-settings" -version = "2.5.2" -description = "Settings management using Pydantic" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pydantic_settings-2.5.2-py3-none-any.whl", hash = "sha256:2c912e55fd5794a59bf8c832b9de832dcfdf4778d79ff79b708744eed499a907"}, - {file = "pydantic_settings-2.5.2.tar.gz", hash = "sha256:f90b139682bee4d2065273d5185d71d37ea46cfe57e1b5ae184fc6a0b2484ca0"}, -] - -[package.dependencies] -pydantic = ">=2.7.0" -python-dotenv = ">=0.21.0" - -[package.extras] -azure-key-vault = ["azure-identity (>=1.16.0)", "azure-keyvault-secrets (>=4.8.0)"] -toml = ["tomli (>=2.0.1)"] -yaml = ["pyyaml (>=6.0.1)"] - -[[package]] -name = "pygments" -version = "2.18.0" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, - {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, -] - -[package.extras] -windows-terminal = ["colorama (>=0.4.6)"] - -[[package]] -name = "pylance" -version = "0.10.12" -description = "python wrapper for Lance columnar format" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"lancedb\"" -files = [ - {file = "pylance-0.10.12-cp38-abi3-macosx_10_15_x86_64.whl", hash = "sha256:30cbcca078edeb37e11ae86cf9287d81ce6c0c07ba77239284b369a4b361497b"}, - {file = "pylance-0.10.12-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:e558163ff6035d518706cc66848497219ccc755e2972b8f3b1706a3e1fd800fd"}, - {file = "pylance-0.10.12-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75afb39f71d7f12429f9b4d380eb6cf6aed179ae5a1c5d16cc768373a1521f87"}, - {file = "pylance-0.10.12-cp38-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:3de391dfc3a99bdb245fd1e27ef242be769a94853f802ef57f246e9a21358d32"}, - {file = "pylance-0.10.12-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:34a5278b90f4cbcf21261353976127aa2ffbbd7d068810f0a2b0c1aa0334022a"}, - {file = "pylance-0.10.12-cp38-abi3-win_amd64.whl", hash = "sha256:6cef5975d513097fd2c22692296c9a5a138928f38d02cd34ab63a7369abc1463"}, -] - -[package.dependencies] -numpy = ">=1.22" -pyarrow = ">=12,<15.0.1" - -[package.extras] -benchmarks = ["pytest-benchmark"] -dev = ["ruff (==0.2.2)"] -ray = ["ray[data] ; python_version < \"3.12\""] -tests = ["boto3", "datasets", "duckdb", "h5py (<3.11)", "ml-dtypes", "pandas", "pillow", "polars[pandas,pyarrow]", "pytest", "tensorflow", "tqdm"] -torch = ["torch"] - -[[package]] -name = "pymilvus" -version = "2.4.3" -description = "Python Sdk for Milvus" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"milvus\"" -files = [ - {file = "pymilvus-2.4.3-py3-none-any.whl", hash = "sha256:38239e89f8d739f665141d0b80908990b5f59681e889e135c234a4a45669a5c8"}, - {file = "pymilvus-2.4.3.tar.gz", hash = "sha256:703ac29296cdce03d6dc2aaebbe959e57745c141a94150e371dc36c61c226cc1"}, -] - -[package.dependencies] -environs = "<=9.5.0" -grpcio = ">=1.49.1,<=1.63.0" -milvus-lite = ">=2.4.0,<2.5.0" -pandas = ">=1.2.4" -protobuf = ">=3.20.0" -setuptools = ">=67" -ujson = ">=2.0.0" - -[package.extras] -bulk-writer = ["azure-storage-blob", "minio (>=7.0.0)", "pyarrow (>=12.0.0)", "requests"] -dev = ["black", "grpcio (==1.62.2)", "grpcio-testing (==1.62.2)", "grpcio-tools (==1.62.2)", "pytest (>=5.3.4)", "pytest-cov (>=2.8.1)", "pytest-timeout (>=1.3.4)", "ruff (>0.4.0)"] -model = ["milvus-model (>=0.1.0)"] - -[[package]] -name = "pyparsing" -version = "3.1.2" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -optional = true -python-versions = ">=3.6.8" -groups = ["main"] -markers = "extra == \"gmail\" or extra == \"googledrive\"" -files = [ - {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"}, - {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"}, -] - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - -[[package]] -name = "pypdf" -version = "5.0.0" -description = "A pure-python PDF library capable of splitting, merging, cropping, and transforming PDF files" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "pypdf-5.0.0-py3-none-any.whl", hash = "sha256:67603e2e96cdf70e676564520933c017d450f16075b9966be5fee128812ace8c"}, - {file = "pypdf-5.0.0.tar.gz", hash = "sha256:5c536ec0f7af8e2f80eb32806964652a562b9abc5477b3c195e2b842725ce55b"}, -] - -[package.dependencies] -typing_extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} - -[package.extras] -crypto = ["PyCryptodome ; python_version == \"3.6\"", "cryptography ; python_version >= \"3.7\""] -dev = ["black", "flit", "pip-tools", "pre-commit (<2.18.0)", "pytest-cov", "pytest-socket", "pytest-timeout", "pytest-xdist", "wheel"] -docs = ["myst_parser", "sphinx", "sphinx_rtd_theme"] -full = ["Pillow (>=8.0.0)", "PyCryptodome ; python_version == \"3.6\"", "cryptography ; python_version >= \"3.7\""] -image = ["Pillow (>=8.0.0)"] - -[[package]] -name = "pypika" -version = "0.48.9" -description = "A SQL query builder API for Python" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "PyPika-0.48.9.tar.gz", hash = "sha256:838836a61747e7c8380cd1b7ff638694b7a7335345d0f559b04b2cd832ad5378"}, -] - -[[package]] -name = "pyproject-hooks" -version = "1.1.0" -description = "Wrappers to call pyproject.toml-based build backend hooks." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "pyproject_hooks-1.1.0-py3-none-any.whl", hash = "sha256:7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2"}, - {file = "pyproject_hooks-1.1.0.tar.gz", hash = "sha256:4b37730834edbd6bd37f26ece6b44802fb1c1ee2ece0e54ddff8bfc06db86965"}, -] - -[[package]] -name = "pyreadline3" -version = "3.4.1" -description = "A python implementation of GNU readline." -optional = false -python-versions = "*" -groups = ["main"] -markers = "sys_platform == \"win32\"" -files = [ - {file = "pyreadline3-3.4.1-py3-none-any.whl", hash = "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb"}, - {file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"}, -] - -[[package]] -name = "pysbd" -version = "0.3.4" -description = "pysbd (Python Sentence Boundary Disambiguation) is a rule-based sentence boundary detection that works out-of-the-box across many languages." -optional = false -python-versions = ">=3" -groups = ["main"] -files = [ - {file = "pysbd-0.3.4-py3-none-any.whl", hash = "sha256:cd838939b7b0b185fcf86b0baf6636667dfb6e474743beeff878e9f42e022953"}, -] - -[[package]] -name = "pytest" -version = "7.4.4" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} - -[package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "pytest-asyncio" -version = "0.21.2" -description = "Pytest support for asyncio" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "pytest_asyncio-0.21.2-py3-none-any.whl", hash = "sha256:ab664c88bb7998f711d8039cacd4884da6430886ae8bbd4eded552ed2004f16b"}, - {file = "pytest_asyncio-0.21.2.tar.gz", hash = "sha256:d67738fc232b94b326b9d060750beb16e0074210b98dd8b58a5239fa2a154f45"}, -] - -[package.dependencies] -pytest = ">=7.0.0" - -[package.extras] -docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] -testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] - -[[package]] -name = "pytest-cov" -version = "4.1.0" -description = "Pytest plugin for measuring coverage." -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, - {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, -] - -[package.dependencies] -coverage = {version = ">=5.2.1", extras = ["toml"]} -pytest = ">=4.6" - -[package.extras] -testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] - -[[package]] -name = "pytest-env" -version = "0.8.2" -description = "py.test plugin that allows you to add environment variables." -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "pytest_env-0.8.2-py3-none-any.whl", hash = "sha256:5e533273f4d9e6a41c3a3120e0c7944aae5674fa773b329f00a5eb1f23c53a38"}, - {file = "pytest_env-0.8.2.tar.gz", hash = "sha256:baed9b3b6bae77bd75b9238e0ed1ee6903a42806ae9d6aeffb8754cd5584d4ff"}, -] - -[package.dependencies] -pytest = ">=7.3.1" - -[package.extras] -test = ["coverage (>=7.2.7)", "pytest-mock (>=3.10)"] - -[[package]] -name = "pytest-mock" -version = "3.14.0" -description = "Thin-wrapper around the mock package for easier use with pytest" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, - {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, -] - -[package.dependencies] -pytest = ">=6.2.5" - -[package.extras] -dev = ["pre-commit", "pytest-asyncio", "tox"] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "python-dotenv" -version = "1.0.1" -description = "Read key-value pairs from a .env file and set them as environment variables" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, - {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, -] - -[package.extras] -cli = ["click (>=5.0)"] - -[[package]] -name = "pytz" -version = "2024.1" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, - {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, -] - -[[package]] -name = "pywin32" -version = "306" -description = "Python for Window Extensions" -optional = false -python-versions = "*" -groups = ["main"] -markers = "platform_system == \"Windows\"" -files = [ - {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, - {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, - {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, - {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, - {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, - {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, - {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, - {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, - {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, - {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, - {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, - {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, - {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, - {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, -] - -[[package]] -name = "pyyaml" -version = "6.0.1" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.6" -groups = ["main", "dev"] -files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, -] - -[[package]] -name = "qdrant-client" -version = "1.10.1" -description = "Client library for the Qdrant vector search engine" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "qdrant_client-1.10.1-py3-none-any.whl", hash = "sha256:b9fb8fe50dd168d92b2998be7c6135d5a229b3a3258ad158cc69c8adf9ff1810"}, - {file = "qdrant_client-1.10.1.tar.gz", hash = "sha256:2284c8c5bb1defb0d9dbacb07d16f344972f395f4f2ed062318476a7951fd84c"}, -] - -[package.dependencies] -grpcio = ">=1.41.0" -grpcio-tools = ">=1.41.0" -httpx = {version = ">=0.20.0", extras = ["http2"]} -numpy = [ - {version = ">=1.21", markers = "python_version >= \"3.8\" and python_version < \"3.12\""}, - {version = ">=1.26", markers = "python_version >= \"3.12\""}, -] -portalocker = ">=2.7.0,<3.0.0" -pydantic = ">=1.10.8" -urllib3 = ">=1.26.14,<3" - -[package.extras] -fastembed = ["fastembed (==0.2.7) ; python_version < \"3.13\""] -fastembed-gpu = ["fastembed-gpu (==0.2.7) ; python_version < \"3.13\""] - -[[package]] -name = "ratelimiter" -version = "1.2.0.post0" -description = "Simple python rate limiting object" -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"lancedb\"" -files = [ - {file = "ratelimiter-1.2.0.post0-py3-none-any.whl", hash = "sha256:a52be07bc0bb0b3674b4b304550f10c769bbb00fead3072e035904474259809f"}, - {file = "ratelimiter-1.2.0.post0.tar.gz", hash = "sha256:5c395dcabdbbde2e5178ef3f89b568a3066454a6ddc223b76473dac22f89b4f7"}, -] - -[package.extras] -test = ["pytest (>=3.0)", "pytest-asyncio ; python_version >= \"3.5\""] - -[[package]] -name = "regex" -version = "2024.5.15" -description = "Alternative regular expression module, to replace re." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"}, - {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"}, - {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"}, - {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"}, - {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"}, - {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"}, - {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"}, - {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"}, - {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"}, - {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"}, - {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"}, - {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"}, - {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"}, - {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"}, -] - -[[package]] -name = "replicate" -version = "0.15.8" -description = "Python client for Replicate" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"llama2\"" -files = [ - {file = "replicate-0.15.8-py3-none-any.whl", hash = "sha256:a5a42e1b2f8a091325ebb7fb14f2c000e79bf818ef1d085730a8247fe28a9067"}, - {file = "replicate-0.15.8.tar.gz", hash = "sha256:a6ca2be3ed5cfe6c3e24602caa61210279b821a5f91ccf818e4c5165ab8db51a"}, -] - -[package.dependencies] -httpx = ">=0.21.0,<1" -packaging = "*" -pydantic = ">1" - -[package.extras] -dev = ["mypy", "pylint", "pytest", "pytest-asyncio", "pytest-recording", "respx", "ruff (>=0.1.3)"] - -[[package]] -name = "requests" -version = "2.32.3" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "requests-oauthlib" -version = "2.0.0" -description = "OAuthlib authentication support for Requests." -optional = false -python-versions = ">=3.4" -groups = ["main"] -files = [ - {file = "requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"}, - {file = "requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36"}, -] - -[package.dependencies] -oauthlib = ">=3.0.0" -requests = ">=2.0.0" - -[package.extras] -rsa = ["oauthlib[signedtoken] (>=3.0.0)"] - -[[package]] -name = "requests-toolbelt" -version = "1.0.0" -description = "A utility belt for advanced users of python-requests" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -files = [ - {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, - {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, -] - -[package.dependencies] -requests = ">=2.0.1,<3.0.0" - -[[package]] -name = "responses" -version = "0.23.3" -description = "A utility library for mocking out the `requests` Python library." -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "responses-0.23.3-py3-none-any.whl", hash = "sha256:e6fbcf5d82172fecc0aa1860fd91e58cbfd96cee5e96da5b63fa6eb3caa10dd3"}, - {file = "responses-0.23.3.tar.gz", hash = "sha256:205029e1cb334c21cb4ec64fc7599be48b859a0fd381a42443cdd600bfe8b16a"}, -] - -[package.dependencies] -pyyaml = "*" -requests = ">=2.30.0,<3.0" -types-PyYAML = "*" -urllib3 = ">=1.25.10,<3.0" - -[package.extras] -tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli ; python_version < \"3.11\"", "tomli-w", "types-requests"] - -[[package]] -name = "retry" -version = "0.9.2" -description = "Easy to use retry decorator." -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"lancedb\"" -files = [ - {file = "retry-0.9.2-py2.py3-none-any.whl", hash = "sha256:ccddf89761fa2c726ab29391837d4327f819ea14d244c232a1d24c67a2f98606"}, - {file = "retry-0.9.2.tar.gz", hash = "sha256:f8bfa8b99b69c4506d6f5bd3b0aabf77f98cdb17f3c9fc3f5ca820033336fba4"}, -] - -[package.dependencies] -decorator = ">=3.4.2" -py = ">=1.4.26,<2.0.0" - -[[package]] -name = "rich" -version = "13.7.1" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false -python-versions = ">=3.7.0" -groups = ["main"] -files = [ - {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, - {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, -] - -[package.dependencies] -markdown-it-py = ">=2.2.0" -pygments = ">=2.13.0,<3.0.0" - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<9)"] - -[[package]] -name = "rsa" -version = "4.9" -description = "Pure-Python RSA implementation" -optional = false -python-versions = ">=3.6,<4" -groups = ["main"] -files = [ - {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, - {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, -] - -[package.dependencies] -pyasn1 = ">=0.1.3" - -[[package]] -name = "ruff" -version = "0.1.15" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "ruff-0.1.15-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5fe8d54df166ecc24106db7dd6a68d44852d14eb0729ea4672bb4d96c320b7df"}, - {file = "ruff-0.1.15-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6f0bfbb53c4b4de117ac4d6ddfd33aa5fc31beeaa21d23c45c6dd249faf9126f"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0d432aec35bfc0d800d4f70eba26e23a352386be3a6cf157083d18f6f5881c8"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9405fa9ac0e97f35aaddf185a1be194a589424b8713e3b97b762336ec79ff807"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c66ec24fe36841636e814b8f90f572a8c0cb0e54d8b5c2d0e300d28a0d7bffec"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:6f8ad828f01e8dd32cc58bc28375150171d198491fc901f6f98d2a39ba8e3ff5"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86811954eec63e9ea162af0ffa9f8d09088bab51b7438e8b6488b9401863c25e"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd4025ac5e87d9b80e1f300207eb2fd099ff8200fa2320d7dc066a3f4622dc6b"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b17b93c02cdb6aeb696effecea1095ac93f3884a49a554a9afa76bb125c114c1"}, - {file = "ruff-0.1.15-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ddb87643be40f034e97e97f5bc2ef7ce39de20e34608f3f829db727a93fb82c5"}, - {file = "ruff-0.1.15-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:abf4822129ed3a5ce54383d5f0e964e7fef74a41e48eb1dfad404151efc130a2"}, - {file = "ruff-0.1.15-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6c629cf64bacfd136c07c78ac10a54578ec9d1bd2a9d395efbee0935868bf852"}, - {file = "ruff-0.1.15-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1bab866aafb53da39c2cadfb8e1c4550ac5340bb40300083eb8967ba25481447"}, - {file = "ruff-0.1.15-py3-none-win32.whl", hash = "sha256:2417e1cb6e2068389b07e6fa74c306b2810fe3ee3476d5b8a96616633f40d14f"}, - {file = "ruff-0.1.15-py3-none-win_amd64.whl", hash = "sha256:3837ac73d869efc4182d9036b1405ef4c73d9b1f88da2413875e34e0d6919587"}, - {file = "ruff-0.1.15-py3-none-win_arm64.whl", hash = "sha256:9a933dfb1c14ec7a33cceb1e49ec4a16b51ce3c20fd42663198746efc0427360"}, - {file = "ruff-0.1.15.tar.gz", hash = "sha256:f6dfa8c1b21c913c326919056c390966648b680966febcb796cc9d1aaab8564e"}, -] - -[[package]] -name = "s3transfer" -version = "0.10.2" -description = "An Amazon S3 Transfer Manager" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "s3transfer-0.10.2-py3-none-any.whl", hash = "sha256:eca1c20de70a39daee580aef4986996620f365c4e0fda6a86100231d62f1bf69"}, - {file = "s3transfer-0.10.2.tar.gz", hash = "sha256:0711534e9356d3cc692fdde846b4a1e4b0cb6519971860796e6bc4c7aea00ef6"}, -] - -[package.dependencies] -botocore = ">=1.33.2,<2.0a0" - -[package.extras] -crt = ["botocore[crt] (>=1.33.2,<2.0a0)"] - -[[package]] -name = "safetensors" -version = "0.4.3" -description = "" -optional = true -python-versions = ">=3.7" -groups = ["main"] -markers = "extra == \"opensource\"" -files = [ - {file = "safetensors-0.4.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:dcf5705cab159ce0130cd56057f5f3425023c407e170bca60b4868048bae64fd"}, - {file = "safetensors-0.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bb4f8c5d0358a31e9a08daeebb68f5e161cdd4018855426d3f0c23bb51087055"}, - {file = "safetensors-0.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70a5319ef409e7f88686a46607cbc3c428271069d8b770076feaf913664a07ac"}, - {file = "safetensors-0.4.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fb9c65bd82f9ef3ce4970dc19ee86be5f6f93d032159acf35e663c6bea02b237"}, - {file = "safetensors-0.4.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:edb5698a7bc282089f64c96c477846950358a46ede85a1c040e0230344fdde10"}, - {file = "safetensors-0.4.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:efcc860be094b8d19ac61b452ec635c7acb9afa77beb218b1d7784c6d41fe8ad"}, - {file = "safetensors-0.4.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d88b33980222085dd6001ae2cad87c6068e0991d4f5ccf44975d216db3b57376"}, - {file = "safetensors-0.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5fc6775529fb9f0ce2266edd3e5d3f10aab068e49f765e11f6f2a63b5367021d"}, - {file = "safetensors-0.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9c6ad011c1b4e3acff058d6b090f1da8e55a332fbf84695cf3100c649cc452d1"}, - {file = "safetensors-0.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8c496c5401c1b9c46d41a7688e8ff5b0310a3b9bae31ce0f0ae870e1ea2b8caf"}, - {file = "safetensors-0.4.3-cp310-none-win32.whl", hash = "sha256:38e2a8666178224a51cca61d3cb4c88704f696eac8f72a49a598a93bbd8a4af9"}, - {file = "safetensors-0.4.3-cp310-none-win_amd64.whl", hash = "sha256:393e6e391467d1b2b829c77e47d726f3b9b93630e6a045b1d1fca67dc78bf632"}, - {file = "safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:22f3b5d65e440cec0de8edaa672efa888030802e11c09b3d6203bff60ebff05a"}, - {file = "safetensors-0.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c4fa560ebd4522adddb71dcd25d09bf211b5634003f015a4b815b7647d62ebe"}, - {file = "safetensors-0.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9afd5358719f1b2cf425fad638fc3c887997d6782da317096877e5b15b2ce93"}, - {file = "safetensors-0.4.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d8c5093206ef4b198600ae484230402af6713dab1bd5b8e231905d754022bec7"}, - {file = "safetensors-0.4.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0b2104df1579d6ba9052c0ae0e3137c9698b2d85b0645507e6fd1813b70931a"}, - {file = "safetensors-0.4.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8cf18888606dad030455d18f6c381720e57fc6a4170ee1966adb7ebc98d4d6a3"}, - {file = "safetensors-0.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0bf4f9d6323d9f86eef5567eabd88f070691cf031d4c0df27a40d3b4aaee755b"}, - {file = "safetensors-0.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:585c9ae13a205807b63bef8a37994f30c917ff800ab8a1ca9c9b5d73024f97ee"}, - {file = "safetensors-0.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faefeb3b81bdfb4e5a55b9bbdf3d8d8753f65506e1d67d03f5c851a6c87150e9"}, - {file = "safetensors-0.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:befdf0167ad626f22f6aac6163477fcefa342224a22f11fdd05abb3995c1783c"}, - {file = "safetensors-0.4.3-cp311-none-win32.whl", hash = "sha256:a7cef55929dcbef24af3eb40bedec35d82c3c2fa46338bb13ecf3c5720af8a61"}, - {file = "safetensors-0.4.3-cp311-none-win_amd64.whl", hash = "sha256:840b7ac0eff5633e1d053cc9db12fdf56b566e9403b4950b2dc85393d9b88d67"}, - {file = "safetensors-0.4.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:22d21760dc6ebae42e9c058d75aa9907d9f35e38f896e3c69ba0e7b213033856"}, - {file = "safetensors-0.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d22c1a10dff3f64d0d68abb8298a3fd88ccff79f408a3e15b3e7f637ef5c980"}, - {file = "safetensors-0.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1648568667f820b8c48317c7006221dc40aced1869908c187f493838a1362bc"}, - {file = "safetensors-0.4.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:446e9fe52c051aeab12aac63d1017e0f68a02a92a027b901c4f8e931b24e5397"}, - {file = "safetensors-0.4.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fef5d70683643618244a4f5221053567ca3e77c2531e42ad48ae05fae909f542"}, - {file = "safetensors-0.4.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a1f4430cc0c9d6afa01214a4b3919d0a029637df8e09675ceef1ca3f0dfa0df"}, - {file = "safetensors-0.4.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d603846a8585b9432a0fd415db1d4c57c0f860eb4aea21f92559ff9902bae4d"}, - {file = "safetensors-0.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a844cdb5d7cbc22f5f16c7e2a0271170750763c4db08381b7f696dbd2c78a361"}, - {file = "safetensors-0.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:88887f69f7a00cf02b954cdc3034ffb383b2303bc0ab481d4716e2da51ddc10e"}, - {file = "safetensors-0.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ee463219d9ec6c2be1d331ab13a8e0cd50d2f32240a81d498266d77d07b7e71e"}, - {file = "safetensors-0.4.3-cp312-none-win32.whl", hash = "sha256:d0dd4a1db09db2dba0f94d15addc7e7cd3a7b0d393aa4c7518c39ae7374623c3"}, - {file = "safetensors-0.4.3-cp312-none-win_amd64.whl", hash = "sha256:d14d30c25897b2bf19b6fb5ff7e26cc40006ad53fd4a88244fdf26517d852dd7"}, - {file = "safetensors-0.4.3-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:d1456f814655b224d4bf6e7915c51ce74e389b413be791203092b7ff78c936dd"}, - {file = "safetensors-0.4.3-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:455d538aa1aae4a8b279344a08136d3f16334247907b18a5c3c7fa88ef0d3c46"}, - {file = "safetensors-0.4.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf476bca34e1340ee3294ef13e2c625833f83d096cfdf69a5342475602004f95"}, - {file = "safetensors-0.4.3-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:02ef3a24face643456020536591fbd3c717c5abaa2737ec428ccbbc86dffa7a4"}, - {file = "safetensors-0.4.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7de32d0d34b6623bb56ca278f90db081f85fb9c5d327e3c18fd23ac64f465768"}, - {file = "safetensors-0.4.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a0deb16a1d3ea90c244ceb42d2c6c276059616be21a19ac7101aa97da448faf"}, - {file = "safetensors-0.4.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c59d51f182c729f47e841510b70b967b0752039f79f1de23bcdd86462a9b09ee"}, - {file = "safetensors-0.4.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1f598b713cc1a4eb31d3b3203557ac308acf21c8f41104cdd74bf640c6e538e3"}, - {file = "safetensors-0.4.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5757e4688f20df083e233b47de43845d1adb7e17b6cf7da5f8444416fc53828d"}, - {file = "safetensors-0.4.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fe746d03ed8d193674a26105e4f0fe6c726f5bb602ffc695b409eaf02f04763d"}, - {file = "safetensors-0.4.3-cp37-none-win32.whl", hash = "sha256:0d5ffc6a80f715c30af253e0e288ad1cd97a3d0086c9c87995e5093ebc075e50"}, - {file = "safetensors-0.4.3-cp37-none-win_amd64.whl", hash = "sha256:a11c374eb63a9c16c5ed146457241182f310902bd2a9c18255781bb832b6748b"}, - {file = "safetensors-0.4.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1e31be7945f66be23f4ec1682bb47faa3df34cb89fc68527de6554d3c4258a4"}, - {file = "safetensors-0.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:03a4447c784917c9bf01d8f2ac5080bc15c41692202cd5f406afba16629e84d6"}, - {file = "safetensors-0.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d244bcafeb1bc06d47cfee71727e775bca88a8efda77a13e7306aae3813fa7e4"}, - {file = "safetensors-0.4.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53c4879b9c6bd7cd25d114ee0ef95420e2812e676314300624594940a8d6a91f"}, - {file = "safetensors-0.4.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74707624b81f1b7f2b93f5619d4a9f00934d5948005a03f2c1845ffbfff42212"}, - {file = "safetensors-0.4.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d52c958dc210265157573f81d34adf54e255bc2b59ded6218500c9b15a750eb"}, - {file = "safetensors-0.4.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f9568f380f513a60139971169c4a358b8731509cc19112369902eddb33faa4d"}, - {file = "safetensors-0.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0d9cd8e1560dfc514b6d7859247dc6a86ad2f83151a62c577428d5102d872721"}, - {file = "safetensors-0.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:89f9f17b0dacb913ed87d57afbc8aad85ea42c1085bd5de2f20d83d13e9fc4b2"}, - {file = "safetensors-0.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1139eb436fd201c133d03c81209d39ac57e129f5e74e34bb9ab60f8d9b726270"}, - {file = "safetensors-0.4.3-cp38-none-win32.whl", hash = "sha256:d9c289f140a9ae4853fc2236a2ffc9a9f2d5eae0cb673167e0f1b8c18c0961ac"}, - {file = "safetensors-0.4.3-cp38-none-win_amd64.whl", hash = "sha256:622afd28968ef3e9786562d352659a37de4481a4070f4ebac883f98c5836563e"}, - {file = "safetensors-0.4.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8651c7299cbd8b4161a36cd6a322fa07d39cd23535b144d02f1c1972d0c62f3c"}, - {file = "safetensors-0.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e375d975159ac534c7161269de24ddcd490df2157b55c1a6eeace6cbb56903f0"}, - {file = "safetensors-0.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:084fc436e317f83f7071fc6a62ca1c513b2103db325cd09952914b50f51cf78f"}, - {file = "safetensors-0.4.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:41a727a7f5e6ad9f1db6951adee21bbdadc632363d79dc434876369a17de6ad6"}, - {file = "safetensors-0.4.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e7dbbde64b6c534548696808a0e01276d28ea5773bc9a2dfb97a88cd3dffe3df"}, - {file = "safetensors-0.4.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bbae3b4b9d997971431c346edbfe6e41e98424a097860ee872721e176040a893"}, - {file = "safetensors-0.4.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01e4b22e3284cd866edeabe4f4d896229495da457229408d2e1e4810c5187121"}, - {file = "safetensors-0.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dd37306546b58d3043eb044c8103a02792cc024b51d1dd16bd3dd1f334cb3ed"}, - {file = "safetensors-0.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8815b5e1dac85fc534a97fd339e12404db557878c090f90442247e87c8aeaea"}, - {file = "safetensors-0.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e011cc162503c19f4b1fd63dfcddf73739c7a243a17dac09b78e57a00983ab35"}, - {file = "safetensors-0.4.3-cp39-none-win32.whl", hash = "sha256:01feb3089e5932d7e662eda77c3ecc389f97c0883c4a12b5cfdc32b589a811c3"}, - {file = "safetensors-0.4.3-cp39-none-win_amd64.whl", hash = "sha256:3f9cdca09052f585e62328c1c2923c70f46814715c795be65f0b93f57ec98a02"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1b89381517891a7bb7d1405d828b2bf5d75528299f8231e9346b8eba092227f9"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:cd6fff9e56df398abc5866b19a32124815b656613c1c5ec0f9350906fd798aac"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:840caf38d86aa7014fe37ade5d0d84e23dcfbc798b8078015831996ecbc206a3"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9650713b2cfa9537a2baf7dd9fee458b24a0aaaa6cafcea8bdd5fb2b8efdc34"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e4119532cd10dba04b423e0f86aecb96cfa5a602238c0aa012f70c3a40c44b50"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e066e8861eef6387b7c772344d1fe1f9a72800e04ee9a54239d460c400c72aab"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:90964917f5b0fa0fa07e9a051fbef100250c04d150b7026ccbf87a34a54012e0"}, - {file = "safetensors-0.4.3-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c41e1893d1206aa7054029681778d9a58b3529d4c807002c156d58426c225173"}, - {file = "safetensors-0.4.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae7613a119a71a497d012ccc83775c308b9c1dab454806291427f84397d852fd"}, - {file = "safetensors-0.4.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9bac020faba7f5dc481e881b14b6425265feabb5bfc552551d21189c0eddc3"}, - {file = "safetensors-0.4.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:420a98f593ff9930f5822560d14c395ccbc57342ddff3b463bc0b3d6b1951550"}, - {file = "safetensors-0.4.3-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f5e6883af9a68c0028f70a4c19d5a6ab6238a379be36ad300a22318316c00cb0"}, - {file = "safetensors-0.4.3-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:cdd0a3b5da66e7f377474599814dbf5cbf135ff059cc73694de129b58a5e8a2c"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9bfb92f82574d9e58401d79c70c716985dc049b635fef6eecbb024c79b2c46ad"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:3615a96dd2dcc30eb66d82bc76cda2565f4f7bfa89fcb0e31ba3cea8a1a9ecbb"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:868ad1b6fc41209ab6bd12f63923e8baeb1a086814cb2e81a65ed3d497e0cf8f"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7ffba80aa49bd09195145a7fd233a7781173b422eeb995096f2b30591639517"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0acbe31340ab150423347e5b9cc595867d814244ac14218932a5cf1dd38eb39"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:19bbdf95de2cf64f25cd614c5236c8b06eb2cfa47cbf64311f4b5d80224623a3"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b852e47eb08475c2c1bd8131207b405793bfc20d6f45aff893d3baaad449ed14"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5d07cbca5b99babb692d76d8151bec46f461f8ad8daafbfd96b2fca40cadae65"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1ab6527a20586d94291c96e00a668fa03f86189b8a9defa2cdd34a1a01acc7d5"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02318f01e332cc23ffb4f6716e05a492c5f18b1d13e343c49265149396284a44"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec4b52ce9a396260eb9731eb6aea41a7320de22ed73a1042c2230af0212758ce"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:018b691383026a2436a22b648873ed11444a364324e7088b99cd2503dd828400"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:309b10dbcab63269ecbf0e2ca10ce59223bb756ca5d431ce9c9eeabd446569da"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b277482120df46e27a58082df06a15aebda4481e30a1c21eefd0921ae7e03f65"}, - {file = "safetensors-0.4.3.tar.gz", hash = "sha256:2f85fc50c4e07a21e95c24e07460fe6f7e2859d0ce88092838352b798ce711c2"}, -] - -[package.extras] -all = ["safetensors[jax]", "safetensors[numpy]", "safetensors[paddlepaddle]", "safetensors[pinned-tf]", "safetensors[quality]", "safetensors[testing]", "safetensors[torch]"] -dev = ["safetensors[all]"] -jax = ["flax (>=0.6.3)", "jax (>=0.3.25)", "jaxlib (>=0.3.25)", "safetensors[numpy]"] -mlx = ["mlx (>=0.0.9)"] -numpy = ["numpy (>=1.21.6)"] -paddlepaddle = ["paddlepaddle (>=2.4.1)", "safetensors[numpy]"] -pinned-tf = ["safetensors[numpy]", "tensorflow (==2.11.0)"] -quality = ["black (==22.3)", "click (==8.0.4)", "flake8 (>=3.8.3)", "isort (>=5.5.4)"] -tensorflow = ["safetensors[numpy]", "tensorflow (>=2.11.0)"] -testing = ["h5py (>=3.7.0)", "huggingface-hub (>=0.12.1)", "hypothesis (>=6.70.2)", "pytest (>=7.2.0)", "pytest-benchmark (>=4.0.0)", "safetensors[numpy]", "setuptools-rust (>=1.5.2)"] -torch = ["safetensors[numpy]", "torch (>=1.10)"] - -[[package]] -name = "schema" -version = "0.7.7" -description = "Simple data validation library" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "schema-0.7.7-py2.py3-none-any.whl", hash = "sha256:5d976a5b50f36e74e2157b47097b60002bd4d42e65425fcc9c9befadb4255dde"}, - {file = "schema-0.7.7.tar.gz", hash = "sha256:7da553abd2958a19dc2547c388cde53398b39196175a9be59ea1caf5ab0a1807"}, -] - -[[package]] -name = "scikit-learn" -version = "1.5.1" -description = "A set of python modules for machine learning and data mining" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"opensource\"" -files = [ - {file = "scikit_learn-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:781586c414f8cc58e71da4f3d7af311e0505a683e112f2f62919e3019abd3745"}, - {file = "scikit_learn-1.5.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f5b213bc29cc30a89a3130393b0e39c847a15d769d6e59539cd86b75d276b1a7"}, - {file = "scikit_learn-1.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ff4ba34c2abff5ec59c803ed1d97d61b036f659a17f55be102679e88f926fac"}, - {file = "scikit_learn-1.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:161808750c267b77b4a9603cf9c93579c7a74ba8486b1336034c2f1579546d21"}, - {file = "scikit_learn-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:10e49170691514a94bb2e03787aa921b82dbc507a4ea1f20fd95557862c98dc1"}, - {file = "scikit_learn-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:154297ee43c0b83af12464adeab378dee2d0a700ccd03979e2b821e7dd7cc1c2"}, - {file = "scikit_learn-1.5.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:b5e865e9bd59396220de49cb4a57b17016256637c61b4c5cc81aaf16bc123bbe"}, - {file = "scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:909144d50f367a513cee6090873ae582dba019cb3fca063b38054fa42704c3a4"}, - {file = "scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:689b6f74b2c880276e365fe84fe4f1befd6a774f016339c65655eaff12e10cbf"}, - {file = "scikit_learn-1.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:9a07f90846313a7639af6a019d849ff72baadfa4c74c778821ae0fad07b7275b"}, - {file = "scikit_learn-1.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5944ce1faada31c55fb2ba20a5346b88e36811aab504ccafb9f0339e9f780395"}, - {file = "scikit_learn-1.5.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:0828673c5b520e879f2af6a9e99eee0eefea69a2188be1ca68a6121b809055c1"}, - {file = "scikit_learn-1.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:508907e5f81390e16d754e8815f7497e52139162fd69c4fdbd2dfa5d6cc88915"}, - {file = "scikit_learn-1.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97625f217c5c0c5d0505fa2af28ae424bd37949bb2f16ace3ff5f2f81fb4498b"}, - {file = "scikit_learn-1.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:da3f404e9e284d2b0a157e1b56b6566a34eb2798205cba35a211df3296ab7a74"}, - {file = "scikit_learn-1.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:88e0672c7ac21eb149d409c74cc29f1d611d5158175846e7a9c2427bd12b3956"}, - {file = "scikit_learn-1.5.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:7b073a27797a283187a4ef4ee149959defc350b46cbf63a84d8514fe16b69855"}, - {file = "scikit_learn-1.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b59e3e62d2be870e5c74af4e793293753565c7383ae82943b83383fdcf5cc5c1"}, - {file = "scikit_learn-1.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd8d3a19d4bd6dc5a7d4f358c8c3a60934dc058f363c34c0ac1e9e12a31421d"}, - {file = "scikit_learn-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:5f57428de0c900a98389c4a433d4a3cf89de979b3aa24d1c1d251802aa15e44d"}, - {file = "scikit_learn-1.5.1.tar.gz", hash = "sha256:0ea5d40c0e3951df445721927448755d3fe1d80833b0b7308ebff5d2a45e6414"}, -] - -[package.dependencies] -joblib = ">=1.2.0" -numpy = ">=1.19.5" -scipy = ">=1.6.0" -threadpoolctl = ">=3.1.0" - -[package.extras] -benchmark = ["matplotlib (>=3.3.4)", "memory_profiler (>=0.57.0)", "pandas (>=1.1.5)"] -build = ["cython (>=3.0.10)", "meson-python (>=0.16.0)", "numpy (>=1.19.5)", "scipy (>=1.6.0)"] -docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.3.4)", "memory_profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.1.5)", "plotly (>=5.14.0)", "polars (>=0.20.23)", "pooch (>=1.6.0)", "pydata-sphinx-theme (>=0.15.3)", "scikit-image (>=0.17.2)", "seaborn (>=0.9.0)", "sphinx (>=7.3.7)", "sphinx-copybutton (>=0.5.2)", "sphinx-design (>=0.5.0)", "sphinx-gallery (>=0.16.0)", "sphinx-prompt (>=1.4.0)", "sphinx-remove-toctrees (>=1.0.0.post1)", "sphinxcontrib-sass (>=0.3.4)", "sphinxext-opengraph (>=0.9.1)"] -examples = ["matplotlib (>=3.3.4)", "pandas (>=1.1.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.17.2)", "seaborn (>=0.9.0)"] -install = ["joblib (>=1.2.0)", "numpy (>=1.19.5)", "scipy (>=1.6.0)", "threadpoolctl (>=3.1.0)"] -maintenance = ["conda-lock (==2.5.6)"] -tests = ["black (>=24.3.0)", "matplotlib (>=3.3.4)", "mypy (>=1.9)", "numpydoc (>=1.2.0)", "pandas (>=1.1.5)", "polars (>=0.20.23)", "pooch (>=1.6.0)", "pyamg (>=4.0.0)", "pyarrow (>=12.0.0)", "pytest (>=7.1.2)", "pytest-cov (>=2.9.0)", "ruff (>=0.2.1)", "scikit-image (>=0.17.2)"] - -[[package]] -name = "scipy" -version = "1.13.1" -description = "Fundamental algorithms for scientific computing in Python" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"opensource\"" -files = [ - {file = "scipy-1.13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:20335853b85e9a49ff7572ab453794298bcf0354d8068c5f6775a0eabf350aca"}, - {file = "scipy-1.13.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d605e9c23906d1994f55ace80e0125c587f96c020037ea6aa98d01b4bd2e222f"}, - {file = "scipy-1.13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfa31f1def5c819b19ecc3a8b52d28ffdcc7ed52bb20c9a7589669dd3c250989"}, - {file = "scipy-1.13.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26264b282b9da0952a024ae34710c2aff7d27480ee91a2e82b7b7073c24722f"}, - {file = "scipy-1.13.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:eccfa1906eacc02de42d70ef4aecea45415f5be17e72b61bafcfd329bdc52e94"}, - {file = "scipy-1.13.1-cp310-cp310-win_amd64.whl", hash = "sha256:2831f0dc9c5ea9edd6e51e6e769b655f08ec6db6e2e10f86ef39bd32eb11da54"}, - {file = "scipy-1.13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:27e52b09c0d3a1d5b63e1105f24177e544a222b43611aaf5bc44d4a0979e32f9"}, - {file = "scipy-1.13.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:54f430b00f0133e2224c3ba42b805bfd0086fe488835effa33fa291561932326"}, - {file = "scipy-1.13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e89369d27f9e7b0884ae559a3a956e77c02114cc60a6058b4e5011572eea9299"}, - {file = "scipy-1.13.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a78b4b3345f1b6f68a763c6e25c0c9a23a9fd0f39f5f3d200efe8feda560a5fa"}, - {file = "scipy-1.13.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45484bee6d65633752c490404513b9ef02475b4284c4cfab0ef946def50b3f59"}, - {file = "scipy-1.13.1-cp311-cp311-win_amd64.whl", hash = "sha256:5713f62f781eebd8d597eb3f88b8bf9274e79eeabf63afb4a737abc6c84ad37b"}, - {file = "scipy-1.13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5d72782f39716b2b3509cd7c33cdc08c96f2f4d2b06d51e52fb45a19ca0c86a1"}, - {file = "scipy-1.13.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:017367484ce5498445aade74b1d5ab377acdc65e27095155e448c88497755a5d"}, - {file = "scipy-1.13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:949ae67db5fa78a86e8fa644b9a6b07252f449dcf74247108c50e1d20d2b4627"}, - {file = "scipy-1.13.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de3ade0e53bc1f21358aa74ff4830235d716211d7d077e340c7349bc3542e884"}, - {file = "scipy-1.13.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2ac65fb503dad64218c228e2dc2d0a0193f7904747db43014645ae139c8fad16"}, - {file = "scipy-1.13.1-cp312-cp312-win_amd64.whl", hash = "sha256:cdd7dacfb95fea358916410ec61bbc20440f7860333aee6d882bb8046264e949"}, - {file = "scipy-1.13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:436bbb42a94a8aeef855d755ce5a465479c721e9d684de76bf61a62e7c2b81d5"}, - {file = "scipy-1.13.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:8335549ebbca860c52bf3d02f80784e91a004b71b059e3eea9678ba994796a24"}, - {file = "scipy-1.13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d533654b7d221a6a97304ab63c41c96473ff04459e404b83275b60aa8f4b7004"}, - {file = "scipy-1.13.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:637e98dcf185ba7f8e663e122ebf908c4702420477ae52a04f9908707456ba4d"}, - {file = "scipy-1.13.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a014c2b3697bde71724244f63de2476925596c24285c7a637364761f8710891c"}, - {file = "scipy-1.13.1-cp39-cp39-win_amd64.whl", hash = "sha256:392e4ec766654852c25ebad4f64e4e584cf19820b980bc04960bca0b0cd6eaa2"}, - {file = "scipy-1.13.1.tar.gz", hash = "sha256:095a87a0312b08dfd6a6155cbbd310a8c51800fc931b8c0b84003014b874ed3c"}, -] - -[package.dependencies] -numpy = ">=1.22.4,<2.3" - -[package.extras] -dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] -doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.12.0)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0)", "sphinx-design (>=0.4.0)"] -test = ["array-api-strict", "asv", "gmpy2", "hypothesis (>=6.30)", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] - -[[package]] -name = "semver" -version = "3.0.2" -description = "Python helper for Semantic Versioning (https://semver.org)" -optional = true -python-versions = ">=3.7" -groups = ["main"] -markers = "extra == \"lancedb\"" -files = [ - {file = "semver-3.0.2-py3-none-any.whl", hash = "sha256:b1ea4686fe70b981f85359eda33199d60c53964284e0cfb4977d243e37cf4bf4"}, - {file = "semver-3.0.2.tar.gz", hash = "sha256:6253adb39c70f6e51afed2fa7152bcd414c411286088fb4b9effb133885ab4cc"}, -] - -[[package]] -name = "sentence-transformers" -version = "2.7.0" -description = "Multilingual text embeddings" -optional = true -python-versions = ">=3.8.0" -groups = ["main"] -markers = "extra == \"opensource\"" -files = [ - {file = "sentence_transformers-2.7.0-py3-none-any.whl", hash = "sha256:6a7276b05a95931581bbfa4ba49d780b2cf6904fa4a171ec7fd66c343f761c98"}, - {file = "sentence_transformers-2.7.0.tar.gz", hash = "sha256:2f7df99d1c021dded471ed2d079e9d1e4fc8e30ecb06f957be060511b36f24ea"}, -] - -[package.dependencies] -huggingface-hub = ">=0.15.1" -numpy = "*" -Pillow = "*" -scikit-learn = "*" -scipy = "*" -torch = ">=1.11.0" -tqdm = "*" -transformers = ">=4.34.0,<5.0.0" - -[package.extras] -dev = ["pre-commit", "pytest", "ruff (>=0.3.0)"] - -[[package]] -name = "setuptools" -version = "70.3.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "setuptools-70.3.0-py3-none-any.whl", hash = "sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc"}, - {file = "setuptools-70.3.0.tar.gz", hash = "sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5"}, -] - -[package.extras] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-ruff (>=0.3.2) ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] - -[[package]] -name = "shapely" -version = "2.0.4" -description = "Manipulation and analysis of geometric objects" -optional = true -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "shapely-2.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:011b77153906030b795791f2fdfa2d68f1a8d7e40bce78b029782ade3afe4f2f"}, - {file = "shapely-2.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9831816a5d34d5170aa9ed32a64982c3d6f4332e7ecfe62dc97767e163cb0b17"}, - {file = "shapely-2.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5c4849916f71dc44e19ed370421518c0d86cf73b26e8656192fcfcda08218fbd"}, - {file = "shapely-2.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:841f93a0e31e4c64d62ea570d81c35de0f6cea224568b2430d832967536308e6"}, - {file = "shapely-2.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b4431f522b277c79c34b65da128029a9955e4481462cbf7ebec23aab61fc58"}, - {file = "shapely-2.0.4-cp310-cp310-win32.whl", hash = "sha256:92a41d936f7d6743f343be265ace93b7c57f5b231e21b9605716f5a47c2879e7"}, - {file = "shapely-2.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:30982f79f21bb0ff7d7d4a4e531e3fcaa39b778584c2ce81a147f95be1cd58c9"}, - {file = "shapely-2.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de0205cb21ad5ddaef607cda9a3191eadd1e7a62a756ea3a356369675230ac35"}, - {file = "shapely-2.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7d56ce3e2a6a556b59a288771cf9d091470116867e578bebced8bfc4147fbfd7"}, - {file = "shapely-2.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:58b0ecc505bbe49a99551eea3f2e8a9b3b24b3edd2a4de1ac0dc17bc75c9ec07"}, - {file = "shapely-2.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:790a168a808bd00ee42786b8ba883307c0e3684ebb292e0e20009588c426da47"}, - {file = "shapely-2.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4310b5494271e18580d61022c0857eb85d30510d88606fa3b8314790df7f367d"}, - {file = "shapely-2.0.4-cp311-cp311-win32.whl", hash = "sha256:63f3a80daf4f867bd80f5c97fbe03314348ac1b3b70fb1c0ad255a69e3749879"}, - {file = "shapely-2.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:c52ed79f683f721b69a10fb9e3d940a468203f5054927215586c5d49a072de8d"}, - {file = "shapely-2.0.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:5bbd974193e2cc274312da16b189b38f5f128410f3377721cadb76b1e8ca5328"}, - {file = "shapely-2.0.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:41388321a73ba1a84edd90d86ecc8bfed55e6a1e51882eafb019f45895ec0f65"}, - {file = "shapely-2.0.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0776c92d584f72f1e584d2e43cfc5542c2f3dd19d53f70df0900fda643f4bae6"}, - {file = "shapely-2.0.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c75c98380b1ede1cae9a252c6dc247e6279403fae38c77060a5e6186c95073ac"}, - {file = "shapely-2.0.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3e700abf4a37b7b8b90532fa6ed5c38a9bfc777098bc9fbae5ec8e618ac8f30"}, - {file = "shapely-2.0.4-cp312-cp312-win32.whl", hash = "sha256:4f2ab0faf8188b9f99e6a273b24b97662194160cc8ca17cf9d1fb6f18d7fb93f"}, - {file = "shapely-2.0.4-cp312-cp312-win_amd64.whl", hash = "sha256:03152442d311a5e85ac73b39680dd64a9892fa42bb08fd83b3bab4fe6999bfa0"}, - {file = "shapely-2.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:994c244e004bc3cfbea96257b883c90a86e8cbd76e069718eb4c6b222a56f78b"}, - {file = "shapely-2.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05ffd6491e9e8958b742b0e2e7c346635033d0a5f1a0ea083547fcc854e5d5cf"}, - {file = "shapely-2.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbdc1140a7d08faa748256438291394967aa54b40009f54e8d9825e75ef6113"}, - {file = "shapely-2.0.4-cp37-cp37m-win32.whl", hash = "sha256:5af4cd0d8cf2912bd95f33586600cac9c4b7c5053a036422b97cfe4728d2eb53"}, - {file = "shapely-2.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:464157509ce4efa5ff285c646a38b49f8c5ef8d4b340f722685b09bb033c5ccf"}, - {file = "shapely-2.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:489c19152ec1f0e5c5e525356bcbf7e532f311bff630c9b6bc2db6f04da6a8b9"}, - {file = "shapely-2.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b79bbd648664aa6f44ef018474ff958b6b296fed5c2d42db60078de3cffbc8aa"}, - {file = "shapely-2.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:674d7baf0015a6037d5758496d550fc1946f34bfc89c1bf247cabdc415d7747e"}, - {file = "shapely-2.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6cd4ccecc5ea5abd06deeaab52fcdba372f649728050c6143cc405ee0c166679"}, - {file = "shapely-2.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb5cdcbbe3080181498931b52a91a21a781a35dcb859da741c0345c6402bf00c"}, - {file = "shapely-2.0.4-cp38-cp38-win32.whl", hash = "sha256:55a38dcd1cee2f298d8c2ebc60fc7d39f3b4535684a1e9e2f39a80ae88b0cea7"}, - {file = "shapely-2.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:ec555c9d0db12d7fd777ba3f8b75044c73e576c720a851667432fabb7057da6c"}, - {file = "shapely-2.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3f9103abd1678cb1b5f7e8e1af565a652e036844166c91ec031eeb25c5ca8af0"}, - {file = "shapely-2.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:263bcf0c24d7a57c80991e64ab57cba7a3906e31d2e21b455f493d4aab534aaa"}, - {file = "shapely-2.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ddf4a9bfaac643e62702ed662afc36f6abed2a88a21270e891038f9a19bc08fc"}, - {file = "shapely-2.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:485246fcdb93336105c29a5cfbff8a226949db37b7473c89caa26c9bae52a242"}, - {file = "shapely-2.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8de4578e838a9409b5b134a18ee820730e507b2d21700c14b71a2b0757396acc"}, - {file = "shapely-2.0.4-cp39-cp39-win32.whl", hash = "sha256:9dab4c98acfb5fb85f5a20548b5c0abe9b163ad3525ee28822ffecb5c40e724c"}, - {file = "shapely-2.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:31c19a668b5a1eadab82ff070b5a260478ac6ddad3a5b62295095174a8d26398"}, - {file = "shapely-2.0.4.tar.gz", hash = "sha256:5dc736127fac70009b8d309a0eeb74f3e08979e530cf7017f2f507ef62e6cfb8"}, -] - -[package.dependencies] -numpy = ">=1.14,<3" - -[package.extras] -docs = ["matplotlib", "numpydoc (==1.1.*)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] -test = ["pytest", "pytest-cov"] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["main"] -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "soupsieve" -version = "2.5" -description = "A modern CSS selector implementation for Beautiful Soup." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, - {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, -] - -[[package]] -name = "sqlalchemy" -version = "2.0.31" -description = "Database Abstraction Library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "SQLAlchemy-2.0.31-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f2a213c1b699d3f5768a7272de720387ae0122f1becf0901ed6eaa1abd1baf6c"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9fea3d0884e82d1e33226935dac990b967bef21315cbcc894605db3441347443"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3ad7f221d8a69d32d197e5968d798217a4feebe30144986af71ada8c548e9fa"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2bee229715b6366f86a95d497c347c22ddffa2c7c96143b59a2aa5cc9eebbc"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cd5b94d4819c0c89280b7c6109c7b788a576084bf0a480ae17c227b0bc41e109"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:750900a471d39a7eeba57580b11983030517a1f512c2cb287d5ad0fcf3aebd58"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-win32.whl", hash = "sha256:7bd112be780928c7f493c1a192cd8c5fc2a2a7b52b790bc5a84203fb4381c6be"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-win_amd64.whl", hash = "sha256:5a48ac4d359f058474fadc2115f78a5cdac9988d4f99eae44917f36aa1476327"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f68470edd70c3ac3b6cd5c2a22a8daf18415203ca1b036aaeb9b0fb6f54e8298"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e2c38c2a4c5c634fe6c3c58a789712719fa1bf9b9d6ff5ebfce9a9e5b89c1ca"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd15026f77420eb2b324dcb93551ad9c5f22fab2c150c286ef1dc1160f110203"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2196208432deebdfe3b22185d46b08f00ac9d7b01284e168c212919891289396"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:352b2770097f41bff6029b280c0e03b217c2dcaddc40726f8f53ed58d8a85da4"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:56d51ae825d20d604583f82c9527d285e9e6d14f9a5516463d9705dab20c3740"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-win32.whl", hash = "sha256:6e2622844551945db81c26a02f27d94145b561f9d4b0c39ce7bfd2fda5776dac"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-win_amd64.whl", hash = "sha256:ccaf1b0c90435b6e430f5dd30a5aede4764942a695552eb3a4ab74ed63c5b8d3"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3b74570d99126992d4b0f91fb87c586a574a5872651185de8297c6f90055ae42"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f77c4f042ad493cb8595e2f503c7a4fe44cd7bd59c7582fd6d78d7e7b8ec52c"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd1591329333daf94467e699e11015d9c944f44c94d2091f4ac493ced0119449"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74afabeeff415e35525bf7a4ecdab015f00e06456166a2eba7590e49f8db940e"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b9c01990d9015df2c6f818aa8f4297d42ee71c9502026bb074e713d496e26b67"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:66f63278db425838b3c2b1c596654b31939427016ba030e951b292e32b99553e"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-win32.whl", hash = "sha256:0b0f658414ee4e4b8cbcd4a9bb0fd743c5eeb81fc858ca517217a8013d282c96"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-win_amd64.whl", hash = "sha256:fa4b1af3e619b5b0b435e333f3967612db06351217c58bfb50cee5f003db2a5a"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f43e93057cf52a227eda401251c72b6fbe4756f35fa6bfebb5d73b86881e59b0"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d337bf94052856d1b330d5fcad44582a30c532a2463776e1651bd3294ee7e58b"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c06fb43a51ccdff3b4006aafee9fcf15f63f23c580675f7734245ceb6b6a9e05"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:b6e22630e89f0e8c12332b2b4c282cb01cf4da0d26795b7eae16702a608e7ca1"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:79a40771363c5e9f3a77f0e28b3302801db08040928146e6808b5b7a40749c88"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-win32.whl", hash = "sha256:501ff052229cb79dd4c49c402f6cb03b5a40ae4771efc8bb2bfac9f6c3d3508f"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-win_amd64.whl", hash = "sha256:597fec37c382a5442ffd471f66ce12d07d91b281fd474289356b1a0041bdf31d"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:dc6d69f8829712a4fd799d2ac8d79bdeff651c2301b081fd5d3fe697bd5b4ab9"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:23b9fbb2f5dd9e630db70fbe47d963c7779e9c81830869bd7d137c2dc1ad05fb"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a21c97efcbb9f255d5c12a96ae14da873233597dfd00a3a0c4ce5b3e5e79704"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26a6a9837589c42b16693cf7bf836f5d42218f44d198f9343dd71d3164ceeeac"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc251477eae03c20fae8db9c1c23ea2ebc47331bcd73927cdcaecd02af98d3c3"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2fd17e3bb8058359fa61248c52c7b09a97cf3c820e54207a50af529876451808"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-win32.whl", hash = "sha256:c76c81c52e1e08f12f4b6a07af2b96b9b15ea67ccdd40ae17019f1c373faa227"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-win_amd64.whl", hash = "sha256:4b600e9a212ed59355813becbcf282cfda5c93678e15c25a0ef896b354423238"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b6cf796d9fcc9b37011d3f9936189b3c8074a02a4ed0c0fbbc126772c31a6d4"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:78fe11dbe37d92667c2c6e74379f75746dc947ee505555a0197cfba9a6d4f1a4"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fc47dc6185a83c8100b37acda27658fe4dbd33b7d5e7324111f6521008ab4fe"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a41514c1a779e2aa9a19f67aaadeb5cbddf0b2b508843fcd7bafdf4c6864005"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:afb6dde6c11ea4525318e279cd93c8734b795ac8bb5dda0eedd9ebaca7fa23f1"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3f9faef422cfbb8fd53716cd14ba95e2ef655400235c3dfad1b5f467ba179c8c"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-win32.whl", hash = "sha256:fc6b14e8602f59c6ba893980bea96571dd0ed83d8ebb9c4479d9ed5425d562e9"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-win_amd64.whl", hash = "sha256:3cb8a66b167b033ec72c3812ffc8441d4e9f5f78f5e31e54dcd4c90a4ca5bebc"}, - {file = "SQLAlchemy-2.0.31-py3-none-any.whl", hash = "sha256:69f3e3c08867a8e4856e92d7afb618b95cdee18e0bc1647b77599722c9a28911"}, - {file = "SQLAlchemy-2.0.31.tar.gz", hash = "sha256:b607489dd4a54de56984a0c7656247504bd5523d9d0ba799aef59d4add009484"}, -] - -[package.dependencies] -greenlet = {version = "!=0.4.17", markers = "python_version < \"3.13\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} -typing-extensions = ">=4.6.0" - -[package.extras] -aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] -aioodbc = ["aioodbc", "greenlet (!=0.4.17)"] -aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"] -asyncio = ["greenlet (!=0.4.17)"] -asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] -mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] -mssql = ["pyodbc"] -mssql-pymssql = ["pymssql"] -mssql-pyodbc = ["pyodbc"] -mypy = ["mypy (>=0.910)"] -mysql = ["mysqlclient (>=1.4.0)"] -mysql-connector = ["mysql-connector-python"] -oracle = ["cx_oracle (>=8)"] -oracle-oracledb = ["oracledb (>=1.0.1)"] -postgresql = ["psycopg2 (>=2.7)"] -postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] -postgresql-pg8000 = ["pg8000 (>=1.29.1)"] -postgresql-psycopg = ["psycopg (>=3.0.7)"] -postgresql-psycopg2binary = ["psycopg2-binary"] -postgresql-psycopg2cffi = ["psycopg2cffi"] -postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] -pymysql = ["pymysql"] -sqlcipher = ["sqlcipher3_binary"] - -[[package]] -name = "starlette" -version = "0.37.2" -description = "The little ASGI library that shines." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, - {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, -] - -[package.dependencies] -anyio = ">=3.4.0,<5" -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} - -[package.extras] -full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] - -[[package]] -name = "sympy" -version = "1.14.0" -description = "Computer algebra system (CAS) in Python" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5"}, - {file = "sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517"}, -] - -[package.dependencies] -mpmath = ">=1.1.0,<1.4" - -[package.extras] -dev = ["hypothesis (>=6.70.0)", "pytest (>=7.1.0)"] - -[[package]] -name = "tabulate" -version = "0.9.0" -description = "Pretty-print tabular data" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, - {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, -] - -[package.extras] -widechars = ["wcwidth"] - -[[package]] -name = "tenacity" -version = "8.5.0" -description = "Retry code until it succeeds" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687"}, - {file = "tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78"}, -] - -[package.extras] -doc = ["reno", "sphinx"] -test = ["pytest", "tornado (>=4.5)", "typeguard"] - -[[package]] -name = "threadpoolctl" -version = "3.5.0" -description = "threadpoolctl" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"opensource\"" -files = [ - {file = "threadpoolctl-3.5.0-py3-none-any.whl", hash = "sha256:56c1e26c150397e58c4926da8eeee87533b1e32bef131bd4bf6a2f45f3185467"}, - {file = "threadpoolctl-3.5.0.tar.gz", hash = "sha256:082433502dd922bf738de0d8bcc4fdcbf0979ff44c42bd40f5af8a282f6fa107"}, -] - -[[package]] -name = "tiktoken" -version = "0.7.0" -description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "tiktoken-0.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485f3cc6aba7c6b6ce388ba634fbba656d9ee27f766216f45146beb4ac18b25f"}, - {file = "tiktoken-0.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e54be9a2cd2f6d6ffa3517b064983fb695c9a9d8aa7d574d1ef3c3f931a99225"}, - {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79383a6e2c654c6040e5f8506f3750db9ddd71b550c724e673203b4f6b4b4590"}, - {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d4511c52caacf3c4981d1ae2df85908bd31853f33d30b345c8b6830763f769c"}, - {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13c94efacdd3de9aff824a788353aa5749c0faee1fbe3816df365ea450b82311"}, - {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8e58c7eb29d2ab35a7a8929cbeea60216a4ccdf42efa8974d8e176d50c9a3df5"}, - {file = "tiktoken-0.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:21a20c3bd1dd3e55b91c1331bf25f4af522c525e771691adbc9a69336fa7f702"}, - {file = "tiktoken-0.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:10c7674f81e6e350fcbed7c09a65bca9356eaab27fb2dac65a1e440f2bcfe30f"}, - {file = "tiktoken-0.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:084cec29713bc9d4189a937f8a35dbdfa785bd1235a34c1124fe2323821ee93f"}, - {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:811229fde1652fedcca7c6dfe76724d0908775b353556d8a71ed74d866f73f7b"}, - {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86b6e7dc2e7ad1b3757e8a24597415bafcfb454cebf9a33a01f2e6ba2e663992"}, - {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1063c5748be36344c7e18c7913c53e2cca116764c2080177e57d62c7ad4576d1"}, - {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:20295d21419bfcca092644f7e2f2138ff947a6eb8cfc732c09cc7d76988d4a89"}, - {file = "tiktoken-0.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:959d993749b083acc57a317cbc643fb85c014d055b2119b739487288f4e5d1cb"}, - {file = "tiktoken-0.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:71c55d066388c55a9c00f61d2c456a6086673ab7dec22dd739c23f77195b1908"}, - {file = "tiktoken-0.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:09ed925bccaa8043e34c519fbb2f99110bd07c6fd67714793c21ac298e449410"}, - {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03c6c40ff1db0f48a7b4d2dafeae73a5607aacb472fa11f125e7baf9dce73704"}, - {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d20b5c6af30e621b4aca094ee61777a44118f52d886dbe4f02b70dfe05c15350"}, - {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d427614c3e074004efa2f2411e16c826f9df427d3c70a54725cae860f09e4bf4"}, - {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8c46d7af7b8c6987fac9b9f61041b452afe92eb087d29c9ce54951280f899a97"}, - {file = "tiktoken-0.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:0bc603c30b9e371e7c4c7935aba02af5994a909fc3c0fe66e7004070858d3f8f"}, - {file = "tiktoken-0.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2398fecd38c921bcd68418675a6d155fad5f5e14c2e92fcf5fe566fa5485a858"}, - {file = "tiktoken-0.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f5f6afb52fb8a7ea1c811e435e4188f2bef81b5e0f7a8635cc79b0eef0193d6"}, - {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:861f9ee616766d736be4147abac500732b505bf7013cfaf019b85892637f235e"}, - {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54031f95c6939f6b78122c0aa03a93273a96365103793a22e1793ee86da31685"}, - {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fffdcb319b614cf14f04d02a52e26b1d1ae14a570f90e9b55461a72672f7b13d"}, - {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c72baaeaefa03ff9ba9688624143c858d1f6b755bb85d456d59e529e17234769"}, - {file = "tiktoken-0.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:131b8aeb043a8f112aad9f46011dced25d62629091e51d9dc1adbf4a1cc6aa98"}, - {file = "tiktoken-0.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cabc6dc77460df44ec5b879e68692c63551ae4fae7460dd4ff17181df75f1db7"}, - {file = "tiktoken-0.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8d57f29171255f74c0aeacd0651e29aa47dff6f070cb9f35ebc14c82278f3b25"}, - {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ee92776fdbb3efa02a83f968c19d4997a55c8e9ce7be821ceee04a1d1ee149c"}, - {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e215292e99cb41fbc96988ef62ea63bb0ce1e15f2c147a61acc319f8b4cbe5bf"}, - {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a81bac94769cab437dd3ab0b8a4bc4e0f9cf6835bcaa88de71f39af1791727a"}, - {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d6d73ea93e91d5ca771256dfc9d1d29f5a554b83821a1dc0891987636e0ae226"}, - {file = "tiktoken-0.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:2bcb28ddf79ffa424f171dfeef9a4daff61a94c631ca6813f43967cb263b83b9"}, - {file = "tiktoken-0.7.0.tar.gz", hash = "sha256:1077266e949c24e0291f6c350433c6f0971365ece2b173a23bc3b9f9defef6b6"}, -] - -[package.dependencies] -regex = ">=2022.1.18" -requests = ">=2.26.0" - -[package.extras] -blobfile = ["blobfile (>=2)"] - -[[package]] -name = "together" -version = "1.2.1" -description = "Python client for Together's Cloud Platform!" -optional = true -python-versions = "<4.0,>=3.8" -groups = ["main"] -markers = "extra == \"together\"" -files = [ - {file = "together-1.2.1-py3-none-any.whl", hash = "sha256:a94408074e0e50b3dab1d4001cb36a3fdbd0e4d6a0e659ecaae6b7b6355f5369"}, - {file = "together-1.2.1.tar.gz", hash = "sha256:c67f724f4612fc76283c92beaf0cc0cc076543021d19dae04fb4e950d9bf0e68"}, -] - -[package.dependencies] -aiohttp = ">=3.9.3,<4.0.0" -click = ">=8.1.7,<9.0.0" -eval-type-backport = ">=0.1.3,<0.3.0" -filelock = ">=3.13.1,<4.0.0" -numpy = [ - {version = ">=1.23.5", markers = "python_version < \"3.12\""}, - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, -] -pillow = ">=10.3.0,<11.0.0" -pyarrow = ">=10.0.1" -pydantic = ">=2.6.3,<3.0.0" -requests = ">=2.31.0,<3.0.0" -tabulate = ">=0.9.0,<0.10.0" -tqdm = ">=4.66.2,<5.0.0" -typer = ">=0.9,<0.13" - -[[package]] -name = "tokenizers" -version = "0.19.1" -description = "" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "tokenizers-0.19.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:952078130b3d101e05ecfc7fc3640282d74ed26bcf691400f872563fca15ac97"}, - {file = "tokenizers-0.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82c8b8063de6c0468f08e82c4e198763e7b97aabfe573fd4cf7b33930ca4df77"}, - {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f03727225feaf340ceeb7e00604825addef622d551cbd46b7b775ac834c1e1c4"}, - {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:453e4422efdfc9c6b6bf2eae00d5e323f263fff62b29a8c9cd526c5003f3f642"}, - {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:02e81bf089ebf0e7f4df34fa0207519f07e66d8491d963618252f2e0729e0b46"}, - {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b07c538ba956843833fee1190cf769c60dc62e1cf934ed50d77d5502194d63b1"}, - {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e28cab1582e0eec38b1f38c1c1fb2e56bce5dc180acb1724574fc5f47da2a4fe"}, - {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b01afb7193d47439f091cd8f070a1ced347ad0f9144952a30a41836902fe09e"}, - {file = "tokenizers-0.19.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7fb297edec6c6841ab2e4e8f357209519188e4a59b557ea4fafcf4691d1b4c98"}, - {file = "tokenizers-0.19.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2e8a3dd055e515df7054378dc9d6fa8c8c34e1f32777fb9a01fea81496b3f9d3"}, - {file = "tokenizers-0.19.1-cp310-none-win32.whl", hash = "sha256:7ff898780a155ea053f5d934925f3902be2ed1f4d916461e1a93019cc7250837"}, - {file = "tokenizers-0.19.1-cp310-none-win_amd64.whl", hash = "sha256:bea6f9947e9419c2fda21ae6c32871e3d398cba549b93f4a65a2d369662d9403"}, - {file = "tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059"}, - {file = "tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14"}, - {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:dadc509cc8a9fe460bd274c0e16ac4184d0958117cf026e0ea8b32b438171594"}, - {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfedf31824ca4915b511b03441784ff640378191918264268e6923da48104acc"}, - {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac11016d0a04aa6487b1513a3a36e7bee7eec0e5d30057c9c0408067345c48d2"}, - {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76951121890fea8330d3a0df9a954b3f2a37e3ec20e5b0530e9a0044ca2e11fe"}, - {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b342d2ce8fc8d00f376af068e3274e2e8649562e3bc6ae4a67784ded6b99428d"}, - {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa"}, - {file = "tokenizers-0.19.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:706a37cc5332f85f26efbe2bdc9ef8a9b372b77e4645331a405073e4b3a8c1c6"}, - {file = "tokenizers-0.19.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:16baac68651701364b0289979ecec728546133e8e8fe38f66fe48ad07996b88b"}, - {file = "tokenizers-0.19.1-cp311-none-win32.whl", hash = "sha256:9ed240c56b4403e22b9584ee37d87b8bfa14865134e3e1c3fb4b2c42fafd3256"}, - {file = "tokenizers-0.19.1-cp311-none-win_amd64.whl", hash = "sha256:ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66"}, - {file = "tokenizers-0.19.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:621d670e1b1c281a1c9698ed89451395d318802ff88d1fc1accff0867a06f153"}, - {file = "tokenizers-0.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d924204a3dbe50b75630bd16f821ebda6a5f729928df30f582fb5aade90c818a"}, - {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4f3fefdc0446b1a1e6d81cd4c07088ac015665d2e812f6dbba4a06267d1a2c95"}, - {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9620b78e0b2d52ef07b0d428323fb34e8ea1219c5eac98c2596311f20f1f9266"}, - {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04ce49e82d100594715ac1b2ce87d1a36e61891a91de774755f743babcd0dd52"}, - {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5c2ff13d157afe413bf7e25789879dd463e5a4abfb529a2d8f8473d8042e28f"}, - {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3174c76efd9d08f836bfccaca7cfec3f4d1c0a4cf3acbc7236ad577cc423c840"}, - {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c9d5b6c0e7a1e979bec10ff960fae925e947aab95619a6fdb4c1d8ff3708ce3"}, - {file = "tokenizers-0.19.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a179856d1caee06577220ebcfa332af046d576fb73454b8f4d4b0ba8324423ea"}, - {file = "tokenizers-0.19.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:952b80dac1a6492170f8c2429bd11fcaa14377e097d12a1dbe0ef2fb2241e16c"}, - {file = "tokenizers-0.19.1-cp312-none-win32.whl", hash = "sha256:01d62812454c188306755c94755465505836fd616f75067abcae529c35edeb57"}, - {file = "tokenizers-0.19.1-cp312-none-win_amd64.whl", hash = "sha256:b70bfbe3a82d3e3fb2a5e9b22a39f8d1740c96c68b6ace0086b39074f08ab89a"}, - {file = "tokenizers-0.19.1-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:bb9dfe7dae85bc6119d705a76dc068c062b8b575abe3595e3c6276480e67e3f1"}, - {file = "tokenizers-0.19.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:1f0360cbea28ea99944ac089c00de7b2e3e1c58f479fb8613b6d8d511ce98267"}, - {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:71e3ec71f0e78780851fef28c2a9babe20270404c921b756d7c532d280349214"}, - {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b82931fa619dbad979c0ee8e54dd5278acc418209cc897e42fac041f5366d626"}, - {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e8ff5b90eabdcdaa19af697885f70fe0b714ce16709cf43d4952f1f85299e73a"}, - {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e742d76ad84acbdb1a8e4694f915fe59ff6edc381c97d6dfdd054954e3478ad4"}, - {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d8c5d59d7b59885eab559d5bc082b2985555a54cda04dda4c65528d90ad252ad"}, - {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b2da5c32ed869bebd990c9420df49813709e953674c0722ff471a116d97b22d"}, - {file = "tokenizers-0.19.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:638e43936cc8b2cbb9f9d8dde0fe5e7e30766a3318d2342999ae27f68fdc9bd6"}, - {file = "tokenizers-0.19.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:78e769eb3b2c79687d9cb0f89ef77223e8e279b75c0a968e637ca7043a84463f"}, - {file = "tokenizers-0.19.1-cp37-none-win32.whl", hash = "sha256:72791f9bb1ca78e3ae525d4782e85272c63faaef9940d92142aa3eb79f3407a3"}, - {file = "tokenizers-0.19.1-cp37-none-win_amd64.whl", hash = "sha256:f3bbb7a0c5fcb692950b041ae11067ac54826204318922da754f908d95619fbc"}, - {file = "tokenizers-0.19.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:07f9295349bbbcedae8cefdbcfa7f686aa420be8aca5d4f7d1ae6016c128c0c5"}, - {file = "tokenizers-0.19.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:10a707cc6c4b6b183ec5dbfc5c34f3064e18cf62b4a938cb41699e33a99e03c1"}, - {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6309271f57b397aa0aff0cbbe632ca9d70430839ca3178bf0f06f825924eca22"}, - {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ad23d37d68cf00d54af184586d79b84075ada495e7c5c0f601f051b162112dc"}, - {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:427c4f0f3df9109314d4f75b8d1f65d9477033e67ffaec4bca53293d3aca286d"}, - {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e83a31c9cf181a0a3ef0abad2b5f6b43399faf5da7e696196ddd110d332519ee"}, - {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c27b99889bd58b7e301468c0838c5ed75e60c66df0d4db80c08f43462f82e0d3"}, - {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bac0b0eb952412b0b196ca7a40e7dce4ed6f6926489313414010f2e6b9ec2adf"}, - {file = "tokenizers-0.19.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8a6298bde623725ca31c9035a04bf2ef63208d266acd2bed8c2cb7d2b7d53ce6"}, - {file = "tokenizers-0.19.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:08a44864e42fa6d7d76d7be4bec62c9982f6f6248b4aa42f7302aa01e0abfd26"}, - {file = "tokenizers-0.19.1-cp38-none-win32.whl", hash = "sha256:1de5bc8652252d9357a666e609cb1453d4f8e160eb1fb2830ee369dd658e8975"}, - {file = "tokenizers-0.19.1-cp38-none-win_amd64.whl", hash = "sha256:0bcce02bf1ad9882345b34d5bd25ed4949a480cf0e656bbd468f4d8986f7a3f1"}, - {file = "tokenizers-0.19.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:0b9394bd204842a2a1fd37fe29935353742be4a3460b6ccbaefa93f58a8df43d"}, - {file = "tokenizers-0.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4692ab92f91b87769d950ca14dbb61f8a9ef36a62f94bad6c82cc84a51f76f6a"}, - {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6258c2ef6f06259f70a682491c78561d492e885adeaf9f64f5389f78aa49a051"}, - {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c85cf76561fbd01e0d9ea2d1cbe711a65400092bc52b5242b16cfd22e51f0c58"}, - {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:670b802d4d82bbbb832ddb0d41df7015b3e549714c0e77f9bed3e74d42400fbe"}, - {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:85aa3ab4b03d5e99fdd31660872249df5e855334b6c333e0bc13032ff4469c4a"}, - {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbf001afbbed111a79ca47d75941e9e5361297a87d186cbfc11ed45e30b5daba"}, - {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c89aa46c269e4e70c4d4f9d6bc644fcc39bb409cb2a81227923404dd6f5227"}, - {file = "tokenizers-0.19.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:39c1ec76ea1027438fafe16ecb0fb84795e62e9d643444c1090179e63808c69d"}, - {file = "tokenizers-0.19.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c2a0d47a89b48d7daa241e004e71fb5a50533718897a4cd6235cb846d511a478"}, - {file = "tokenizers-0.19.1-cp39-none-win32.whl", hash = "sha256:61b7fe8886f2e104d4caf9218b157b106207e0f2a4905c9c7ac98890688aabeb"}, - {file = "tokenizers-0.19.1-cp39-none-win_amd64.whl", hash = "sha256:f97660f6c43efd3e0bfd3f2e3e5615bf215680bad6ee3d469df6454b8c6e8256"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3b11853f17b54c2fe47742c56d8a33bf49ce31caf531e87ac0d7d13d327c9334"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d26194ef6c13302f446d39972aaa36a1dda6450bc8949f5eb4c27f51191375bd"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e8d1ed93beda54bbd6131a2cb363a576eac746d5c26ba5b7556bc6f964425594"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca407133536f19bdec44b3da117ef0d12e43f6d4b56ac4c765f37eca501c7bda"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce05fde79d2bc2e46ac08aacbc142bead21614d937aac950be88dc79f9db9022"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:35583cd46d16f07c054efd18b5d46af4a2f070a2dd0a47914e66f3ff5efb2b1e"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:43350270bfc16b06ad3f6f07eab21f089adb835544417afda0f83256a8bf8b75"}, - {file = "tokenizers-0.19.1-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b4399b59d1af5645bcee2072a463318114c39b8547437a7c2d6a186a1b5a0e2d"}, - {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6852c5b2a853b8b0ddc5993cd4f33bfffdca4fcc5d52f89dd4b8eada99379285"}, - {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcd266ae85c3d39df2f7e7d0e07f6c41a55e9a3123bb11f854412952deacd828"}, - {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecb2651956eea2aa0a2d099434134b1b68f1c31f9a5084d6d53f08ed43d45ff2"}, - {file = "tokenizers-0.19.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:b279ab506ec4445166ac476fb4d3cc383accde1ea152998509a94d82547c8e2a"}, - {file = "tokenizers-0.19.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:89183e55fb86e61d848ff83753f64cded119f5d6e1f553d14ffee3700d0a4a49"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2edbc75744235eea94d595a8b70fe279dd42f3296f76d5a86dde1d46e35f574"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0e64bfde9a723274e9a71630c3e9494ed7b4c0f76a1faacf7fe294cd26f7ae7c"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0b5ca92bfa717759c052e345770792d02d1f43b06f9e790ca0a1db62838816f3"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f8a20266e695ec9d7a946a019c1d5ca4eddb6613d4f466888eee04f16eedb85"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63c38f45d8f2a2ec0f3a20073cccb335b9f99f73b3c69483cd52ebc75369d8a1"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dd26e3afe8a7b61422df3176e06664503d3f5973b94f45d5c45987e1cb711876"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:eddd5783a4a6309ce23432353cdb36220e25cbb779bfa9122320666508b44b88"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:56ae39d4036b753994476a1b935584071093b55c7a72e3b8288e68c313ca26e7"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f9939ca7e58c2758c01b40324a59c034ce0cebad18e0d4563a9b1beab3018243"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c330c0eb815d212893c67a032e9dc1b38a803eccb32f3e8172c19cc69fbb439"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec11802450a2487cdf0e634b750a04cbdc1c4d066b97d94ce7dd2cb51ebb325b"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2b718f316b596f36e1dae097a7d5b91fc5b85e90bf08b01ff139bd8953b25af"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:ed69af290c2b65169f0ba9034d1dc39a5db9459b32f1dd8b5f3f32a3fcf06eab"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f8a9c828277133af13f3859d1b6bf1c3cb6e9e1637df0e45312e6b7c2e622b1f"}, - {file = "tokenizers-0.19.1.tar.gz", hash = "sha256:ee59e6680ed0fdbe6b724cf38bd70400a0c1dd623b07ac729087270caeac88e3"}, -] - -[package.dependencies] -huggingface-hub = ">=0.16.4,<1.0" - -[package.extras] -dev = ["tokenizers[testing]"] -docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"] -testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests", "ruff"] - -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -markers = "python_version < \"3.11\"" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] - -[[package]] -name = "torch" -version = "2.8.0" -description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration" -optional = true -python-versions = ">=3.9.0" -groups = ["main"] -markers = "python_version == \"3.9\" and extra == \"opensource\"" -files = [ - {file = "torch-2.8.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:0be92c08b44009d4131d1ff7a8060d10bafdb7ddcb7359ef8d8c5169007ea905"}, - {file = "torch-2.8.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:89aa9ee820bb39d4d72b794345cccef106b574508dd17dbec457949678c76011"}, - {file = "torch-2.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e8e5bf982e87e2b59d932769938b698858c64cc53753894be25629bdf5cf2f46"}, - {file = "torch-2.8.0-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:a3f16a58a9a800f589b26d47ee15aca3acf065546137fc2af039876135f4c760"}, - {file = "torch-2.8.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:220a06fd7af8b653c35d359dfe1aaf32f65aa85befa342629f716acb134b9710"}, - {file = "torch-2.8.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:c12fa219f51a933d5f80eeb3a7a5d0cbe9168c0a14bbb4055f1979431660879b"}, - {file = "torch-2.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:8c7ef765e27551b2fbfc0f41bcf270e1292d9bf79f8e0724848b1682be6e80aa"}, - {file = "torch-2.8.0-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:5ae0524688fb6707c57a530c2325e13bb0090b745ba7b4a2cd6a3ce262572916"}, - {file = "torch-2.8.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:e2fab4153768d433f8ed9279c8133a114a034a61e77a3a104dcdf54388838705"}, - {file = "torch-2.8.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2aca0939fb7e4d842561febbd4ffda67a8e958ff725c1c27e244e85e982173c"}, - {file = "torch-2.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:2f4ac52f0130275d7517b03a33d2493bab3693c83dcfadf4f81688ea82147d2e"}, - {file = "torch-2.8.0-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:619c2869db3ada2c0105487ba21b5008defcc472d23f8b80ed91ac4a380283b0"}, - {file = "torch-2.8.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:2b2f96814e0345f5a5aed9bf9734efa913678ed19caf6dc2cddb7930672d6128"}, - {file = "torch-2.8.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:65616ca8ec6f43245e1f5f296603e33923f4c30f93d65e103d9e50c25b35150b"}, - {file = "torch-2.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:659df54119ae03e83a800addc125856effda88b016dfc54d9f65215c3975be16"}, - {file = "torch-2.8.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:1a62a1ec4b0498930e2543535cf70b1bef8c777713de7ceb84cd79115f553767"}, - {file = "torch-2.8.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:83c13411a26fac3d101fe8035a6b0476ae606deb8688e904e796a3534c197def"}, - {file = "torch-2.8.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:8f0a9d617a66509ded240add3754e462430a6c1fc5589f86c17b433dd808f97a"}, - {file = "torch-2.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:a7242b86f42be98ac674b88a4988643b9bc6145437ec8f048fea23f72feb5eca"}, - {file = "torch-2.8.0-cp313-none-macosx_11_0_arm64.whl", hash = "sha256:7b677e17f5a3e69fdef7eb3b9da72622f8d322692930297e4ccb52fefc6c8211"}, - {file = "torch-2.8.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:da6afa31c13b669d4ba49d8a2169f0db2c3ec6bec4af898aa714f401d4c38904"}, - {file = "torch-2.8.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:06fcee8000e5c62a9f3e52a688b9c5abb7c6228d0e56e3452983416025c41381"}, - {file = "torch-2.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:5128fe752a355d9308e56af1ad28b15266fe2da5948660fad44de9e3a9e36e8c"}, - {file = "torch-2.8.0-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:e9f071f5b52a9f6970dc8a919694b27a91ae9dc08898b2b988abbef5eddfd1ae"}, -] - -[package.dependencies] -filelock = "*" -fsspec = "*" -jinja2 = "*" -networkx = "*" -nvidia-cublas-cu12 = {version = "12.8.4.1", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-cuda-cupti-cu12 = {version = "12.8.90", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-cuda-nvrtc-cu12 = {version = "12.8.93", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-cuda-runtime-cu12 = {version = "12.8.90", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-cudnn-cu12 = {version = "9.10.2.21", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-cufft-cu12 = {version = "11.3.3.83", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-cufile-cu12 = {version = "1.13.1.3", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-curand-cu12 = {version = "10.3.9.90", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-cusolver-cu12 = {version = "11.7.3.90", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-cusparse-cu12 = {version = "12.5.8.93", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-cusparselt-cu12 = {version = "0.7.1", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-nccl-cu12 = {version = "2.27.3", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-nvjitlink-cu12 = {version = "12.8.93", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -nvidia-nvtx-cu12 = {version = "12.8.90", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -sympy = ">=1.13.3" -triton = {version = "3.4.0", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} -typing-extensions = ">=4.10.0" - -[package.extras] -opt-einsum = ["opt-einsum (>=3.3)"] -optree = ["optree (>=0.13.0)"] -pyyaml = ["pyyaml"] - -[[package]] -name = "torch" -version = "2.11.0" -description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "python_version >= \"3.10\" and extra == \"opensource\"" -files = [ - {file = "torch-2.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2c0d7fcfbc0c4e8bb5ebc3907cbc0c6a0da1b8f82b1fc6e14e914fa0b9baf74e"}, - {file = "torch-2.11.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:4cf8687f4aec3900f748d553483ef40e0ac38411c3c48d0a86a438f6d7a99b18"}, - {file = "torch-2.11.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:1b32ceda909818a03b112006709b02be1877240c31750a8d9c6b7bf5f2d8a6e5"}, - {file = "torch-2.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:b3c712ae6fb8e7a949051a953fc412fe0a6940337336c3b6f905e905dac5157f"}, - {file = "torch-2.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7b6a60d48062809f58595509c524b88e6ddec3ebe25833d6462eeab81e5f2ce4"}, - {file = "torch-2.11.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:d91aac77f24082809d2c5a93f52a5f085032740a1ebc9252a7b052ef5a4fddc6"}, - {file = "torch-2.11.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:7aa2f9bbc6d4595ba72138026b2074be1233186150e9292865e04b7a63b8c67a"}, - {file = "torch-2.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:73e24aaf8f36ab90d95cd1761208b2eb70841c2a9ca1a3f9061b39fc5331b708"}, - {file = "torch-2.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4b5866312ee6e52ea625cd211dcb97d6a2cdc1131a5f15cc0d87eec948f6dd34"}, - {file = "torch-2.11.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f99924682ef0aa6a4ab3b1b76f40dc6e273fca09f367d15a524266db100a723f"}, - {file = "torch-2.11.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:0f68f4ac6d95d12e896c3b7a912b5871619542ec54d3649cf48cc1edd4dd2756"}, - {file = "torch-2.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:fbf39280699d1b869f55eac536deceaa1b60bd6788ba74f399cc67e60a5fab10"}, - {file = "torch-2.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1e6debd97ccd3205bbb37eb806a9d8219e1139d15419982c09e23ef7d4369d18"}, - {file = "torch-2.11.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:63a68fa59de8f87acc7e85a5478bb2dddbb3392b7593ec3e78827c793c4b73fd"}, - {file = "torch-2.11.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:cc89b9b173d9adfab59fd227f0ab5e5516d9a52b658ae41d64e59d2e55a418db"}, - {file = "torch-2.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:4dda3b3f52d121063a731ddb835f010dc137b920d7fec2778e52f60d8e4bf0cd"}, - {file = "torch-2.11.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8b394322f49af4362d4f80e424bcaca7efcd049619af03a4cf4501520bdf0fb4"}, - {file = "torch-2.11.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:2658f34ce7e2dabf4ec73b45e2ca68aedad7a5be87ea756ad656eaf32bf1e1ea"}, - {file = "torch-2.11.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:98bb213c3084cfe176302949bdc360074b18a9da7ab59ef2edc9d9f742504778"}, - {file = "torch-2.11.0-cp313-cp313t-win_amd64.whl", hash = "sha256:a97b94bbf62992949b4730c6cd2cc9aee7b335921ee8dc207d930f2ed09ae2db"}, - {file = "torch-2.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:01018087326984a33b64e04c8cb5c2795f9120e0d775ada1f6638840227b04d7"}, - {file = "torch-2.11.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:2bb3cc54bd0dea126b0060bb1ec9de0f9c7f7342d93d436646516b0330cd5be7"}, - {file = "torch-2.11.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:4dc8b3809469b6c30b411bb8c4cad3828efd26236153d9beb6a3ec500f211a60"}, - {file = "torch-2.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:2b4e811728bd0cc58fb2b0948fe939a1ee2bf1422f6025be2fca4c7bd9d79718"}, - {file = "torch-2.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8245477871c3700d4370352ffec94b103cfcb737229445cf9946cddb7b2ca7cd"}, - {file = "torch-2.11.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:ab9a8482f475f9ba20e12db84b0e55e2f58784bdca43a854a6ccd3fd4b9f75e6"}, - {file = "torch-2.11.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:563ed3d25542d7e7bbc5b235ccfacfeb97fb470c7fee257eae599adb8005c8a2"}, - {file = "torch-2.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b2a43985ff5ef6ddd923bbcf99943e5f58059805787c5c9a2622bf05ca2965b0"}, -] - -[package.dependencies] -cuda-bindings = {version = ">=13.0.3,<14", markers = "platform_system == \"Linux\""} -cuda-toolkit = {version = "13.0.2", extras = ["cublas", "cudart", "cufft", "cufile", "cupti", "curand", "cusolver", "cusparse", "nvjitlink", "nvrtc", "nvtx"], markers = "platform_system == \"Linux\""} -filelock = "*" -fsspec = ">=0.8.5" -jinja2 = "*" -networkx = ">=2.5.1" -nvidia-cudnn-cu13 = {version = "9.19.0.56", markers = "platform_system == \"Linux\""} -nvidia-cusparselt-cu13 = {version = "0.8.0", markers = "platform_system == \"Linux\""} -nvidia-nccl-cu13 = {version = "2.28.9", markers = "platform_system == \"Linux\""} -nvidia-nvshmem-cu13 = {version = "3.4.5", markers = "platform_system == \"Linux\""} -setuptools = "<82" -sympy = ">=1.13.3" -triton = {version = "3.6.0", markers = "platform_system == \"Linux\""} -typing-extensions = ">=4.10.0" - -[package.extras] -opt-einsum = ["opt-einsum (>=3.3)"] -optree = ["optree (>=0.13.0)"] -pyyaml = ["pyyaml"] - -[[package]] -name = "tqdm" -version = "4.66.4" -description = "Fast, Extensible Progress Meter" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "tqdm-4.66.4-py3-none-any.whl", hash = "sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644"}, - {file = "tqdm-4.66.4.tar.gz", hash = "sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] -notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] - -[[package]] -name = "transformers" -version = "4.42.4" -description = "State-of-the-art Machine Learning for JAX, PyTorch and TensorFlow" -optional = true -python-versions = ">=3.8.0" -groups = ["main"] -markers = "extra == \"opensource\"" -files = [ - {file = "transformers-4.42.4-py3-none-any.whl", hash = "sha256:6d59061392d0f1da312af29c962df9017ff3c0108c681a56d1bc981004d16d24"}, - {file = "transformers-4.42.4.tar.gz", hash = "sha256:f956e25e24df851f650cb2c158b6f4352dfae9d702f04c113ed24fc36ce7ae2d"}, -] - -[package.dependencies] -filelock = "*" -huggingface-hub = ">=0.23.2,<1.0" -numpy = ">=1.17,<2.0" -packaging = ">=20.0" -pyyaml = ">=5.1" -regex = "!=2019.12.17" -requests = "*" -safetensors = ">=0.4.1" -tokenizers = ">=0.19,<0.20" -tqdm = ">=4.27" - -[package.extras] -accelerate = ["accelerate (>=0.21.0)"] -agents = ["Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "datasets (!=2.5.0)", "diffusers", "opencv-python", "sentencepiece (>=0.1.91,!=0.1.92)", "torch"] -all = ["Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "av (==9.2.0)", "codecarbon (==1.2.0)", "decord (==0.6.0)", "flax (>=0.4.1,<=0.7.0)", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "phonemizer", "protobuf", "pyctcdecode (>=0.4.0)", "ray[tune] (>=2.7.0)", "scipy (<1.13.0)", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "tensorflow (>2.9,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timm (<=0.9.16)", "tokenizers (>=0.19,<0.20)", "torch", "torchaudio", "torchvision"] -audio = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)"] -benchmark = ["optimum-benchmark (>=0.2.0)"] -codecarbon = ["codecarbon (==1.2.0)"] -deepspeed = ["accelerate (>=0.21.0)", "deepspeed (>=0.9.3)"] -deepspeed-testing = ["GitPython (<3.1.19)", "accelerate (>=0.21.0)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "deepspeed (>=0.9.3)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "nltk", "optuna", "parameterized", "protobuf", "psutil", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.4.4)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorboard", "timeout-decorator"] -dev = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "av (==9.2.0)", "beautifulsoup4", "codecarbon (==1.2.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "decord (==0.6.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "flax (>=0.4.1,<=0.7.0)", "fugashi (>=1.0)", "ipadic (>=1.0.0,<2.0)", "isort (>=5.5.4)", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "nltk", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "ray[tune] (>=2.7.0)", "rhoknp (>=1.1.0,<1.3.1)", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.4.4)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "scipy (<1.13.0)", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "tensorboard", "tensorflow (>2.9,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timeout-decorator", "timm (<=0.9.16)", "tokenizers (>=0.19,<0.20)", "torch", "torchaudio", "torchvision", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)", "urllib3 (<2.0.0)"] -dev-tensorflow = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "isort (>=5.5.4)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "nltk", "onnxconverter-common", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.4.4)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorboard", "tensorflow (>2.9,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timeout-decorator", "tokenizers (>=0.19,<0.20)", "urllib3 (<2.0.0)"] -dev-torch = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "beautifulsoup4", "codecarbon (==1.2.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "fugashi (>=1.0)", "ipadic (>=1.0.0,<2.0)", "isort (>=5.5.4)", "kenlm", "librosa", "nltk", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "optuna", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "ray[tune] (>=2.7.0)", "rhoknp (>=1.1.0,<1.3.1)", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.4.4)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "tensorboard", "timeout-decorator", "timm (<=0.9.16)", "tokenizers (>=0.19,<0.20)", "torch", "torchaudio", "torchvision", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)", "urllib3 (<2.0.0)"] -flax = ["flax (>=0.4.1,<=0.7.0)", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "optax (>=0.0.8,<=0.1.4)", "scipy (<1.13.0)"] -flax-speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)"] -ftfy = ["ftfy"] -integrations = ["optuna", "ray[tune] (>=2.7.0)", "sigopt"] -ja = ["fugashi (>=1.0)", "ipadic (>=1.0.0,<2.0)", "rhoknp (>=1.1.0,<1.3.1)", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)"] -modelcreation = ["cookiecutter (==1.7.3)"] -natten = ["natten (>=0.14.6,<0.15.0)"] -onnx = ["onnxconverter-common", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "tf2onnx"] -onnxruntime = ["onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)"] -optuna = ["optuna"] -quality = ["GitPython (<3.1.19)", "datasets (!=2.5.0)", "isort (>=5.5.4)", "ruff (==0.4.4)", "urllib3 (<2.0.0)"] -ray = ["ray[tune] (>=2.7.0)"] -retrieval = ["datasets (!=2.5.0)", "faiss-cpu"] -ruff = ["ruff (==0.4.4)"] -sagemaker = ["sagemaker (>=2.31.0)"] -sentencepiece = ["protobuf", "sentencepiece (>=0.1.91,!=0.1.92)"] -serving = ["fastapi", "pydantic", "starlette", "uvicorn"] -sigopt = ["sigopt"] -sklearn = ["scikit-learn"] -speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)", "torchaudio"] -testing = ["GitPython (<3.1.19)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "nltk", "parameterized", "psutil", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-rich", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.4.4)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorboard", "timeout-decorator"] -tf = ["keras-nlp (>=0.3.1)", "onnxconverter-common", "tensorflow (>2.9,<2.16)", "tensorflow-text (<2.16)", "tf2onnx"] -tf-cpu = ["keras (>2.9,<2.16)", "keras-nlp (>=0.3.1)", "onnxconverter-common", "tensorflow-cpu (>2.9,<2.16)", "tensorflow-probability (<0.24)", "tensorflow-text (<2.16)", "tf2onnx"] -tf-speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)"] -timm = ["timm (<=0.9.16)"] -tokenizers = ["tokenizers (>=0.19,<0.20)"] -torch = ["accelerate (>=0.21.0)", "torch"] -torch-speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)", "torchaudio"] -torch-vision = ["Pillow (>=10.0.1,<=15.0)", "torchvision"] -torchhub = ["filelock", "huggingface-hub (>=0.23.2,<1.0)", "importlib-metadata", "numpy (>=1.17,<2.0)", "packaging (>=20.0)", "protobuf", "regex (!=2019.12.17)", "requests", "sentencepiece (>=0.1.91,!=0.1.92)", "tokenizers (>=0.19,<0.20)", "torch", "tqdm (>=4.27)"] -video = ["av (==9.2.0)", "decord (==0.6.0)"] -vision = ["Pillow (>=10.0.1,<=15.0)"] - -[[package]] -name = "triton" -version = "3.4.0" -description = "A language and compiler for custom Deep Learning operations" -optional = true -python-versions = "<3.14,>=3.9" -groups = ["main"] -markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and extra == \"opensource\" and python_version == \"3.9\"" -files = [ - {file = "triton-3.4.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ff2785de9bc02f500e085420273bb5cc9c9bb767584a4aa28d6e360cec70128"}, - {file = "triton-3.4.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b70f5e6a41e52e48cfc087436c8a28c17ff98db369447bcaff3b887a3ab4467"}, - {file = "triton-3.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:31c1d84a5c0ec2c0f8e8a072d7fd150cab84a9c239eaddc6706c081bfae4eb04"}, - {file = "triton-3.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00be2964616f4c619193cb0d1b29a99bd4b001d7dc333816073f92cf2a8ccdeb"}, - {file = "triton-3.4.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7936b18a3499ed62059414d7df563e6c163c5e16c3773678a3ee3d417865035d"}, - {file = "triton-3.4.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:98e5c1442eaeabae2e2452ae765801bd53cd4ce873cab0d1bdd59a32ab2d9397"}, -] - -[package.dependencies] -importlib-metadata = {version = "*", markers = "python_version < \"3.10\""} -setuptools = ">=40.8.0" - -[package.extras] -build = ["cmake (>=3.20,<4.0)", "lit"] -tests = ["autopep8", "isort", "llnl-hatchet", "numpy", "pytest", "pytest-forked", "pytest-xdist", "scipy (>=1.7.1)"] -tutorials = ["matplotlib", "pandas", "tabulate"] - -[[package]] -name = "triton" -version = "3.6.0" -description = "A language and compiler for custom Deep Learning operations" -optional = true -python-versions = "<3.15,>=3.10" -groups = ["main"] -markers = "extra == \"opensource\" and platform_system == \"Linux\" and python_version >= \"3.10\"" -files = [ - {file = "triton-3.6.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6c723cfb12f6842a0ae94ac307dba7e7a44741d720a40cf0e270ed4a4e3be781"}, - {file = "triton-3.6.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a6550fae429e0667e397e5de64b332d1e5695b73650ee75a6146e2e902770bea"}, - {file = "triton-3.6.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49df5ef37379c0c2b5c0012286f80174fcf0e073e5ade1ca9a86c36814553651"}, - {file = "triton-3.6.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8e323d608e3a9bfcc2d9efcc90ceefb764a82b99dea12a86d643c72539ad5d3"}, - {file = "triton-3.6.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:374f52c11a711fd062b4bfbb201fd9ac0a5febd28a96fb41b4a0f51dde3157f4"}, - {file = "triton-3.6.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:74caf5e34b66d9f3a429af689c1c7128daba1d8208df60e81106b115c00d6fca"}, - {file = "triton-3.6.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:448e02fe6dc898e9e5aa89cf0ee5c371e99df5aa5e8ad976a80b93334f3494fd"}, - {file = "triton-3.6.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10c7f76c6e72d2ef08df639e3d0d30729112f47a56b0c81672edc05ee5116ac9"}, - {file = "triton-3.6.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1722e172d34e32abc3eb7711d0025bb69d7959ebea84e3b7f7a341cd7ed694d6"}, - {file = "triton-3.6.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d002e07d7180fd65e622134fbd980c9a3d4211fb85224b56a0a0efbd422ab72f"}, - {file = "triton-3.6.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef5523241e7d1abca00f1d240949eebdd7c673b005edbbce0aca95b8191f1d43"}, - {file = "triton-3.6.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a17a5d5985f0ac494ed8a8e54568f092f7057ef60e1b0fa09d3fd1512064e803"}, - {file = "triton-3.6.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b3a97e8ed304dfa9bd23bb41ca04cdf6b2e617d5e782a8653d616037a5d537d"}, - {file = "triton-3.6.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:46bd1c1af4b6704e554cad2eeb3b0a6513a980d470ccfa63189737340c7746a7"}, -] - -[package.extras] -build = ["cmake (>=3.20,<4.0)", "lit"] -tests = ["autopep8", "isort", "llnl-hatchet", "numpy", "pytest", "pytest-forked", "pytest-xdist", "scipy (>=1.7.1)"] -tutorials = ["matplotlib", "pandas", "tabulate"] - -[[package]] -name = "typer" -version = "0.9.4" -description = "Typer, build great CLIs. Easy to code. Based on Python type hints." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "typer-0.9.4-py3-none-any.whl", hash = "sha256:aa6c4a4e2329d868b80ecbaf16f807f2b54e192209d7ac9dd42691d63f7a54eb"}, - {file = "typer-0.9.4.tar.gz", hash = "sha256:f714c2d90afae3a7929fcd72a3abb08df305e1ff61719381384211c4070af57f"}, -] - -[package.dependencies] -click = ">=7.1.1,<9.0.0" -typing-extensions = ">=3.7.4.3" - -[package.extras] -all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] -dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"] -doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"] -test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.971)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] - -[[package]] -name = "types-pyyaml" -version = "6.0.12.20240311" -description = "Typing stubs for PyYAML" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "types-PyYAML-6.0.12.20240311.tar.gz", hash = "sha256:a9e0f0f88dc835739b0c1ca51ee90d04ca2a897a71af79de9aec5f38cb0a5342"}, - {file = "types_PyYAML-6.0.12.20240311-py3-none-any.whl", hash = "sha256:b845b06a1c7e54b8e5b4c683043de0d9caf205e7434b3edc678ff2411979b8f6"}, -] - -[[package]] -name = "types-requests" -version = "2.31.0.6" -description = "Typing stubs for requests" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "types-requests-2.31.0.6.tar.gz", hash = "sha256:cd74ce3b53c461f1228a9b783929ac73a666658f223e28ed29753771477b3bd0"}, - {file = "types_requests-2.31.0.6-py3-none-any.whl", hash = "sha256:a2db9cb228a81da8348b49ad6db3f5519452dd20a9c1e1a868c83c5fe88fd1a9"}, -] - -[package.dependencies] -types-urllib3 = "*" - -[[package]] -name = "types-urllib3" -version = "1.26.25.14" -description = "Typing stubs for urllib3" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f"}, - {file = "types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e"}, -] - -[[package]] -name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, -] -markers = {dev = "python_version < \"3.11\""} - -[[package]] -name = "typing-inspect" -version = "0.9.0" -description = "Runtime inspection utilities for typing module." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f"}, - {file = "typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78"}, -] - -[package.dependencies] -mypy-extensions = ">=0.3.0" -typing-extensions = ">=3.7.4" - -[[package]] -name = "tzdata" -version = "2024.1" -description = "Provider of IANA time zone data" -optional = false -python-versions = ">=2" -groups = ["main"] -files = [ - {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, - {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, -] - -[[package]] -name = "ujson" -version = "5.10.0" -description = "Ultra fast JSON encoder and decoder for Python" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"milvus\"" -files = [ - {file = "ujson-5.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd"}, - {file = "ujson-5.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf"}, - {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6"}, - {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569"}, - {file = "ujson-5.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770"}, - {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1"}, - {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5"}, - {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51"}, - {file = "ujson-5.10.0-cp310-cp310-win32.whl", hash = "sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518"}, - {file = "ujson-5.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f"}, - {file = "ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00"}, - {file = "ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126"}, - {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8"}, - {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b"}, - {file = "ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9"}, - {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f"}, - {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4"}, - {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1"}, - {file = "ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f"}, - {file = "ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720"}, - {file = "ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5"}, - {file = "ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e"}, - {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043"}, - {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1"}, - {file = "ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3"}, - {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21"}, - {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2"}, - {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e"}, - {file = "ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e"}, - {file = "ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc"}, - {file = "ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287"}, - {file = "ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e"}, - {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557"}, - {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988"}, - {file = "ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816"}, - {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20"}, - {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0"}, - {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f"}, - {file = "ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165"}, - {file = "ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539"}, - {file = "ujson-5.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a984a3131da7f07563057db1c3020b1350a3e27a8ec46ccbfbf21e5928a43050"}, - {file = "ujson-5.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73814cd1b9db6fc3270e9d8fe3b19f9f89e78ee9d71e8bd6c9a626aeaeaf16bd"}, - {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61e1591ed9376e5eddda202ec229eddc56c612b61ac6ad07f96b91460bb6c2fb"}, - {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2c75269f8205b2690db4572a4a36fe47cd1338e4368bc73a7a0e48789e2e35a"}, - {file = "ujson-5.10.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7223f41e5bf1f919cd8d073e35b229295aa8e0f7b5de07ed1c8fddac63a6bc5d"}, - {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc2fd6b3067c0782e7002ac3b38cf48608ee6366ff176bbd02cf969c9c20fe"}, - {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:232cc85f8ee3c454c115455195a205074a56ff42608fd6b942aa4c378ac14dd7"}, - {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cc6139531f13148055d691e442e4bc6601f6dba1e6d521b1585d4788ab0bfad4"}, - {file = "ujson-5.10.0-cp38-cp38-win32.whl", hash = "sha256:e7ce306a42b6b93ca47ac4a3b96683ca554f6d35dd8adc5acfcd55096c8dfcb8"}, - {file = "ujson-5.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:e82d4bb2138ab05e18f089a83b6564fee28048771eb63cdecf4b9b549de8a2cc"}, - {file = "ujson-5.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dfef2814c6b3291c3c5f10065f745a1307d86019dbd7ea50e83504950136ed5b"}, - {file = "ujson-5.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4734ee0745d5928d0ba3a213647f1c4a74a2a28edc6d27b2d6d5bd9fa4319e27"}, - {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d47ebb01bd865fdea43da56254a3930a413f0c5590372a1241514abae8aa7c76"}, - {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dee5e97c2496874acbf1d3e37b521dd1f307349ed955e62d1d2f05382bc36dd5"}, - {file = "ujson-5.10.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7490655a2272a2d0b072ef16b0b58ee462f4973a8f6bbe64917ce5e0a256f9c0"}, - {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba17799fcddaddf5c1f75a4ba3fd6441f6a4f1e9173f8a786b42450851bd74f1"}, - {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2aff2985cef314f21d0fecc56027505804bc78802c0121343874741650a4d3d1"}, - {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad88ac75c432674d05b61184178635d44901eb749786c8eb08c102330e6e8996"}, - {file = "ujson-5.10.0-cp39-cp39-win32.whl", hash = "sha256:2544912a71da4ff8c4f7ab5606f947d7299971bdd25a45e008e467ca638d13c9"}, - {file = "ujson-5.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:3ff201d62b1b177a46f113bb43ad300b424b7847f9c5d38b1b4ad8f75d4a282a"}, - {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64"}, - {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3"}, - {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a"}, - {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746"}, - {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88"}, - {file = "ujson-5.10.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b"}, - {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7663960f08cd5a2bb152f5ee3992e1af7690a64c0e26d31ba7b3ff5b2ee66337"}, - {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:d8640fb4072d36b08e95a3a380ba65779d356b2fee8696afeb7794cf0902d0a1"}, - {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78778a3aa7aafb11e7ddca4e29f46bc5139131037ad628cc10936764282d6753"}, - {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0111b27f2d5c820e7f2dbad7d48e3338c824e7ac4d2a12da3dc6061cc39c8e6"}, - {file = "ujson-5.10.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c66962ca7565605b355a9ed478292da628b8f18c0f2793021ca4425abf8b01e5"}, - {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4"}, - {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8"}, - {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b"}, - {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804"}, - {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e"}, - {file = "ujson-5.10.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7"}, - {file = "ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1"}, -] - -[[package]] -name = "uritemplate" -version = "4.1.1" -description = "Implementation of RFC 6570 URI Templates" -optional = true -python-versions = ">=3.6" -groups = ["main"] -markers = "extra == \"gmail\" or extra == \"googledrive\"" -files = [ - {file = "uritemplate-4.1.1-py2.py3-none-any.whl", hash = "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e"}, - {file = "uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0"}, -] - -[[package]] -name = "urllib3" -version = "1.26.19" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -groups = ["main", "dev"] -files = [ - {file = "urllib3-1.26.19-py2.py3-none-any.whl", hash = "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3"}, - {file = "urllib3-1.26.19.tar.gz", hash = "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429"}, -] - -[package.extras] -brotli = ["brotli (==1.0.9) ; os_name != \"nt\" and python_version < \"3\" and platform_python_implementation == \"CPython\"", "brotli (>=1.0.9) ; python_version >= \"3\" and platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; (os_name != \"nt\" or python_version >= \"3\") and platform_python_implementation != \"CPython\"", "brotlipy (>=0.6.0) ; os_name == \"nt\" and python_version < \"3\""] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress ; python_version == \"2.7\"", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] - -[[package]] -name = "uuid-utils" -version = "0.14.1" -description = "Fast, drop-in replacement for Python's uuid module, powered by Rust." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "uuid_utils-0.14.1-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:93a3b5dc798a54a1feb693f2d1cb4cf08258c32ff05ae4929b5f0a2ca624a4f0"}, - {file = "uuid_utils-0.14.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:ccd65a4b8e83af23eae5e56d88034b2fe7264f465d3e830845f10d1591b81741"}, - {file = "uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b56b0cacd81583834820588378e432b0696186683b813058b707aedc1e16c4b1"}, - {file = "uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb3cf14de789097320a3c56bfdfdd51b1225d11d67298afbedee7e84e3837c96"}, - {file = "uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60e0854a90d67f4b0cc6e54773deb8be618f4c9bad98d3326f081423b5d14fae"}, - {file = "uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce6743ba194de3910b5feb1a62590cd2587e33a73ab6af8a01b642ceb5055862"}, - {file = "uuid_utils-0.14.1-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:043fb58fde6cf1620a6c066382f04f87a8e74feb0f95a585e4ed46f5d44af57b"}, - {file = "uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c915d53f22945e55fe0d3d3b0b87fd965a57f5fd15666fd92d6593a73b1dd297"}, - {file = "uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:0972488e3f9b449e83f006ead5a0e0a33ad4a13e4462e865b7c286ab7d7566a3"}, - {file = "uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:1c238812ae0c8ffe77d8d447a32c6dfd058ea4631246b08b5a71df586ff08531"}, - {file = "uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:bec8f8ef627af86abf8298e7ec50926627e29b34fa907fcfbedb45aaa72bca43"}, - {file = "uuid_utils-0.14.1-cp39-abi3-win32.whl", hash = "sha256:b54d6aa6252d96bac1fdbc80d26ba71bad9f220b2724d692ad2f2310c22ef523"}, - {file = "uuid_utils-0.14.1-cp39-abi3-win_amd64.whl", hash = "sha256:fc27638c2ce267a0ce3e06828aff786f91367f093c80625ee21dad0208e0f5ba"}, - {file = "uuid_utils-0.14.1-cp39-abi3-win_arm64.whl", hash = "sha256:b04cb49b42afbc4ff8dbc60cf054930afc479d6f4dd7f1ec3bbe5dbfdde06b7a"}, - {file = "uuid_utils-0.14.1-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:b197cd5424cf89fb019ca7f53641d05bfe34b1879614bed111c9c313b5574cd8"}, - {file = "uuid_utils-0.14.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:12c65020ba6cb6abe1d57fcbfc2d0ea0506c67049ee031714057f5caf0f9bc9c"}, - {file = "uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b5d2ad28063d422ccc2c28d46471d47b61a58de885d35113a8f18cb547e25bf"}, - {file = "uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:da2234387b45fde40b0fedfee64a0ba591caeea9c48c7698ab6e2d85c7991533"}, - {file = "uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50fffc2827348c1e48972eed3d1c698959e63f9d030aa5dd82ba451113158a62"}, - {file = "uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1dbe718765f70f5b7f9b7f66b6a937802941b1cc56bcf642ce0274169741e01"}, - {file = "uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:258186964039a8e36db10810c1ece879d229b01331e09e9030bc5dcabe231bd2"}, - {file = "uuid_utils-0.14.1.tar.gz", hash = "sha256:9bfc95f64af80ccf129c604fb6b8ca66c6f256451e32bc4570f760e4309c9b69"}, -] - -[[package]] -name = "uvicorn" -version = "0.30.1" -description = "The lightning-fast ASGI server." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "uvicorn-0.30.1-py3-none-any.whl", hash = "sha256:cd17daa7f3b9d7a24de3617820e634d0933b69eed8e33a516071174427238c81"}, - {file = "uvicorn-0.30.1.tar.gz", hash = "sha256:d46cd8e0fd80240baffbcd9ec1012a712938754afcf81bce56c024c1656aece8"}, -] - -[package.dependencies] -click = ">=7.0" -colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} -h11 = ">=0.8" -httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""} -python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} -pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} -typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} -uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and extra == \"standard\""} -watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} -websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} - -[package.extras] -standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchfiles (>=0.13)", "websockets (>=10.4)"] - -[[package]] -name = "uvloop" -version = "0.19.0" -description = "Fast implementation of asyncio event loop on top of libuv" -optional = false -python-versions = ">=3.8.0" -groups = ["main"] -markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"" -files = [ - {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"}, - {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428"}, - {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8"}, - {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849"}, - {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957"}, - {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd"}, - {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef"}, - {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2"}, - {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1"}, - {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24"}, - {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533"}, - {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12"}, - {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650"}, - {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec"}, - {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc"}, - {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6"}, - {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593"}, - {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3"}, - {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd"}, - {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd"}, - {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be"}, - {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797"}, - {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d"}, - {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7"}, - {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b"}, - {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67"}, - {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7"}, - {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256"}, - {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17"}, - {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5"}, - {file = "uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd"}, -] - -[package.extras] -docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] -test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0) ; python_version >= \"3.12\"", "aiohttp (>=3.8.1) ; python_version < \"3.12\"", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] - -[[package]] -name = "validators" -version = "0.32.0" -description = "Python Data Validation for Humans™" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"weaviate\"" -files = [ - {file = "validators-0.32.0-py3-none-any.whl", hash = "sha256:e9ce1703afb0adf7724b0f98e4081d9d10e88fa5d37254d21e41f27774c020cd"}, - {file = "validators-0.32.0.tar.gz", hash = "sha256:9ee6e6d7ac9292b9b755a3155d7c361d76bb2dce23def4f0627662da1e300676"}, -] - -[package.extras] -crypto-eth-addresses = ["eth-hash[pycryptodome] (>=0.7.0)"] - -[[package]] -name = "virtualenv" -version = "20.26.3" -description = "Virtual Python Environment builder" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "virtualenv-20.26.3-py3-none-any.whl", hash = "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589"}, - {file = "virtualenv-20.26.3.tar.gz", hash = "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a"}, -] - -[package.dependencies] -distlib = ">=0.3.7,<1" -filelock = ">=3.12.2,<4" -platformdirs = ">=3.9.1,<5" - -[package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] - -[[package]] -name = "watchfiles" -version = "0.22.0" -description = "Simple, modern and high performance file watching and code reload in python." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "watchfiles-0.22.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:da1e0a8caebf17976e2ffd00fa15f258e14749db5e014660f53114b676e68538"}, - {file = "watchfiles-0.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61af9efa0733dc4ca462347becb82e8ef4945aba5135b1638bfc20fad64d4f0e"}, - {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d9188979a58a096b6f8090e816ccc3f255f137a009dd4bbec628e27696d67c1"}, - {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2bdadf6b90c099ca079d468f976fd50062905d61fae183f769637cb0f68ba59a"}, - {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:067dea90c43bf837d41e72e546196e674f68c23702d3ef80e4e816937b0a3ffd"}, - {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbf8a20266136507abf88b0df2328e6a9a7c7309e8daff124dda3803306a9fdb"}, - {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1235c11510ea557fe21be5d0e354bae2c655a8ee6519c94617fe63e05bca4171"}, - {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2444dc7cb9d8cc5ab88ebe792a8d75709d96eeef47f4c8fccb6df7c7bc5be71"}, - {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c5af2347d17ab0bd59366db8752d9e037982e259cacb2ba06f2c41c08af02c39"}, - {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9624a68b96c878c10437199d9a8b7d7e542feddda8d5ecff58fdc8e67b460848"}, - {file = "watchfiles-0.22.0-cp310-none-win32.whl", hash = "sha256:4b9f2a128a32a2c273d63eb1fdbf49ad64852fc38d15b34eaa3f7ca2f0d2b797"}, - {file = "watchfiles-0.22.0-cp310-none-win_amd64.whl", hash = "sha256:2627a91e8110b8de2406d8b2474427c86f5a62bf7d9ab3654f541f319ef22bcb"}, - {file = "watchfiles-0.22.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8c39987a1397a877217be1ac0fb1d8b9f662c6077b90ff3de2c05f235e6a8f96"}, - {file = "watchfiles-0.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a927b3034d0672f62fb2ef7ea3c9fc76d063c4b15ea852d1db2dc75fe2c09696"}, - {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052d668a167e9fc345c24203b104c313c86654dd6c0feb4b8a6dfc2462239249"}, - {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e45fb0d70dda1623a7045bd00c9e036e6f1f6a85e4ef2c8ae602b1dfadf7550"}, - {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c49b76a78c156979759d759339fb62eb0549515acfe4fd18bb151cc07366629c"}, - {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4a65474fd2b4c63e2c18ac67a0c6c66b82f4e73e2e4d940f837ed3d2fd9d4da"}, - {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc0cba54f47c660d9fa3218158b8963c517ed23bd9f45fe463f08262a4adae1"}, - {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ebe84a035993bb7668f58a0ebf998174fb723a39e4ef9fce95baabb42b787f"}, - {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e0f0a874231e2839abbf473256efffe577d6ee2e3bfa5b540479e892e47c172d"}, - {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:213792c2cd3150b903e6e7884d40660e0bcec4465e00563a5fc03f30ea9c166c"}, - {file = "watchfiles-0.22.0-cp311-none-win32.whl", hash = "sha256:b44b70850f0073b5fcc0b31ede8b4e736860d70e2dbf55701e05d3227a154a67"}, - {file = "watchfiles-0.22.0-cp311-none-win_amd64.whl", hash = "sha256:00f39592cdd124b4ec5ed0b1edfae091567c72c7da1487ae645426d1b0ffcad1"}, - {file = "watchfiles-0.22.0-cp311-none-win_arm64.whl", hash = "sha256:3218a6f908f6a276941422b035b511b6d0d8328edd89a53ae8c65be139073f84"}, - {file = "watchfiles-0.22.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c7b978c384e29d6c7372209cbf421d82286a807bbcdeb315427687f8371c340a"}, - {file = "watchfiles-0.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd4c06100bce70a20c4b81e599e5886cf504c9532951df65ad1133e508bf20be"}, - {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:425440e55cd735386ec7925f64d5dde392e69979d4c8459f6bb4e920210407f2"}, - {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68fe0c4d22332d7ce53ad094622b27e67440dacefbaedd29e0794d26e247280c"}, - {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a8a31bfd98f846c3c284ba694c6365620b637debdd36e46e1859c897123aa232"}, - {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc2e8fe41f3cac0660197d95216c42910c2b7e9c70d48e6d84e22f577d106fc1"}, - {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b7cc10261c2786c41d9207193a85c1db1b725cf87936df40972aab466179b6"}, - {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28585744c931576e535860eaf3f2c0ec7deb68e3b9c5a85ca566d69d36d8dd27"}, - {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00095dd368f73f8f1c3a7982a9801190cc88a2f3582dd395b289294f8975172b"}, - {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:52fc9b0dbf54d43301a19b236b4a4614e610605f95e8c3f0f65c3a456ffd7d35"}, - {file = "watchfiles-0.22.0-cp312-none-win32.whl", hash = "sha256:581f0a051ba7bafd03e17127735d92f4d286af941dacf94bcf823b101366249e"}, - {file = "watchfiles-0.22.0-cp312-none-win_amd64.whl", hash = "sha256:aec83c3ba24c723eac14225194b862af176d52292d271c98820199110e31141e"}, - {file = "watchfiles-0.22.0-cp312-none-win_arm64.whl", hash = "sha256:c668228833c5619f6618699a2c12be057711b0ea6396aeaece4ded94184304ea"}, - {file = "watchfiles-0.22.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d47e9ef1a94cc7a536039e46738e17cce058ac1593b2eccdede8bf72e45f372a"}, - {file = "watchfiles-0.22.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28f393c1194b6eaadcdd8f941307fc9bbd7eb567995232c830f6aef38e8a6e88"}, - {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd64f3a4db121bc161644c9e10a9acdb836853155a108c2446db2f5ae1778c3d"}, - {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2abeb79209630da981f8ebca30a2c84b4c3516a214451bfc5f106723c5f45843"}, - {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cc382083afba7918e32d5ef12321421ef43d685b9a67cc452a6e6e18920890e"}, - {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d048ad5d25b363ba1d19f92dcf29023988524bee6f9d952130b316c5802069cb"}, - {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:103622865599f8082f03af4214eaff90e2426edff5e8522c8f9e93dc17caee13"}, - {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3e1f3cf81f1f823e7874ae563457828e940d75573c8fbf0ee66818c8b6a9099"}, - {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8597b6f9dc410bdafc8bb362dac1cbc9b4684a8310e16b1ff5eee8725d13dcd6"}, - {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0b04a2cbc30e110303baa6d3ddce8ca3664bc3403be0f0ad513d1843a41c97d1"}, - {file = "watchfiles-0.22.0-cp38-none-win32.whl", hash = "sha256:b610fb5e27825b570554d01cec427b6620ce9bd21ff8ab775fc3a32f28bba63e"}, - {file = "watchfiles-0.22.0-cp38-none-win_amd64.whl", hash = "sha256:fe82d13461418ca5e5a808a9e40f79c1879351fcaeddbede094028e74d836e86"}, - {file = "watchfiles-0.22.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3973145235a38f73c61474d56ad6199124e7488822f3a4fc97c72009751ae3b0"}, - {file = "watchfiles-0.22.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:280a4afbc607cdfc9571b9904b03a478fc9f08bbeec382d648181c695648202f"}, - {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a0d883351a34c01bd53cfa75cd0292e3f7e268bacf2f9e33af4ecede7e21d1d"}, - {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9165bcab15f2b6d90eedc5c20a7f8a03156b3773e5fb06a790b54ccecdb73385"}, - {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc1b9b56f051209be458b87edb6856a449ad3f803315d87b2da4c93b43a6fe72"}, - {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dc1fc25a1dedf2dd952909c8e5cb210791e5f2d9bc5e0e8ebc28dd42fed7562"}, - {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc92d2d2706d2b862ce0568b24987eba51e17e14b79a1abcd2edc39e48e743c8"}, - {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97b94e14b88409c58cdf4a8eaf0e67dfd3ece7e9ce7140ea6ff48b0407a593ec"}, - {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96eec15e5ea7c0b6eb5bfffe990fc7c6bd833acf7e26704eb18387fb2f5fd087"}, - {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:28324d6b28bcb8d7c1041648d7b63be07a16db5510bea923fc80b91a2a6cbed6"}, - {file = "watchfiles-0.22.0-cp39-none-win32.whl", hash = "sha256:8c3e3675e6e39dc59b8fe5c914a19d30029e36e9f99468dddffd432d8a7b1c93"}, - {file = "watchfiles-0.22.0-cp39-none-win_amd64.whl", hash = "sha256:25c817ff2a86bc3de3ed2df1703e3d24ce03479b27bb4527c57e722f8554d971"}, - {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b810a2c7878cbdecca12feae2c2ae8af59bea016a78bc353c184fa1e09f76b68"}, - {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7e1f9c5d1160d03b93fc4b68a0aeb82fe25563e12fbcdc8507f8434ab6f823c"}, - {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:030bc4e68d14bcad2294ff68c1ed87215fbd9a10d9dea74e7cfe8a17869785ab"}, - {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace7d060432acde5532e26863e897ee684780337afb775107c0a90ae8dbccfd2"}, - {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5834e1f8b71476a26df97d121c0c0ed3549d869124ed2433e02491553cb468c2"}, - {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0bc3b2f93a140df6806c8467c7f51ed5e55a931b031b5c2d7ff6132292e803d6"}, - {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fdebb655bb1ba0122402352b0a4254812717a017d2dc49372a1d47e24073795"}, - {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c8e0aa0e8cc2a43561e0184c0513e291ca891db13a269d8d47cb9841ced7c71"}, - {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2f350cbaa4bb812314af5dab0eb8d538481e2e2279472890864547f3fe2281ed"}, - {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7a74436c415843af2a769b36bf043b6ccbc0f8d784814ba3d42fc961cdb0a9dc"}, - {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00ad0bcd399503a84cc688590cdffbe7a991691314dde5b57b3ed50a41319a31"}, - {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72a44e9481afc7a5ee3291b09c419abab93b7e9c306c9ef9108cb76728ca58d2"}, - {file = "watchfiles-0.22.0.tar.gz", hash = "sha256:988e981aaab4f3955209e7e28c7794acdb690be1efa7f16f8ea5aba7ffdadacb"}, -] - -[package.dependencies] -anyio = ">=3.0.0" - -[[package]] -name = "weaviate-client" -version = "3.26.5" -description = "A python native Weaviate client" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"weaviate\"" -files = [ - {file = "weaviate_client-3.26.5-py3-none-any.whl", hash = "sha256:76327ba93bdfff293e7e299e90ea28ad0e489cfff7c7a6be82c72d1159b60e4f"}, - {file = "weaviate_client-3.26.5.tar.gz", hash = "sha256:f9dc0e42656e3458b12aa59b73e08da0e0f6301f3cd368473c9f5242821854d6"}, -] - -[package.dependencies] -authlib = ">=1.2.1,<2.0.0" -requests = ">=2.30.0,<3.0.0" -validators = ">=0.21.2,<1.0.0" - -[package.extras] -grpc = ["grpcio (>=1.57.0,<2.0.0)", "grpcio-tools (>=1.57.0,<2.0.0)"] - -[[package]] -name = "websocket-client" -version = "1.8.0" -description = "WebSocket client for Python with low level API options" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, - {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, -] - -[package.extras] -docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] -optional = ["python-socks", "wsaccel"] -test = ["websockets"] - -[[package]] -name = "websockets" -version = "12.0" -description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, - {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, - {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"}, - {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"}, - {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"}, - {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"}, - {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"}, - {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"}, - {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"}, - {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"}, - {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"}, - {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"}, - {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"}, - {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"}, - {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"}, - {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"}, - {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"}, - {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"}, - {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"}, - {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"}, - {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"}, - {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"}, - {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"}, - {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"}, - {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"}, - {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"}, - {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"}, - {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"}, - {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"}, - {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"}, - {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"}, - {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"}, - {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, -] - -[[package]] -name = "wrapt" -version = "1.16.0" -description = "Module for decorators, wrappers and monkey patching." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, - {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, - {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, - {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, - {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, - {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, - {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, - {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, - {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, - {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, - {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, - {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, - {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, - {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, - {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, - {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, - {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, - {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, -] - -[[package]] -name = "yarl" -version = "1.9.4" -description = "Yet another URL library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, - {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, - {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, - {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, - {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, - {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, - {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, - {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, - {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, - {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, - {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, - {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, - {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, - {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, - {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, - {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" - -[[package]] -name = "zipp" -version = "3.19.2" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, - {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, -] - -[package.extras] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -test = ["big-O", "importlib-resources ; python_version < \"3.9\"", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] - -[[package]] -name = "zstandard" -version = "0.23.0" -description = "Zstandard bindings for Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "zstandard-0.23.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bf0a05b6059c0528477fba9054d09179beb63744355cab9f38059548fedd46a9"}, - {file = "zstandard-0.23.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fc9ca1c9718cb3b06634c7c8dec57d24e9438b2aa9a0f02b8bb36bf478538880"}, - {file = "zstandard-0.23.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77da4c6bfa20dd5ea25cbf12c76f181a8e8cd7ea231c673828d0386b1740b8dc"}, - {file = "zstandard-0.23.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2170c7e0367dde86a2647ed5b6f57394ea7f53545746104c6b09fc1f4223573"}, - {file = "zstandard-0.23.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c16842b846a8d2a145223f520b7e18b57c8f476924bda92aeee3a88d11cfc391"}, - {file = "zstandard-0.23.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:157e89ceb4054029a289fb504c98c6a9fe8010f1680de0201b3eb5dc20aa6d9e"}, - {file = "zstandard-0.23.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:203d236f4c94cd8379d1ea61db2fce20730b4c38d7f1c34506a31b34edc87bdd"}, - {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dc5d1a49d3f8262be192589a4b72f0d03b72dcf46c51ad5852a4fdc67be7b9e4"}, - {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:752bf8a74412b9892f4e5b58f2f890a039f57037f52c89a740757ebd807f33ea"}, - {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80080816b4f52a9d886e67f1f96912891074903238fe54f2de8b786f86baded2"}, - {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:84433dddea68571a6d6bd4fbf8ff398236031149116a7fff6f777ff95cad3df9"}, - {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ab19a2d91963ed9e42b4e8d77cd847ae8381576585bad79dbd0a8837a9f6620a"}, - {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:59556bf80a7094d0cfb9f5e50bb2db27fefb75d5138bb16fb052b61b0e0eeeb0"}, - {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:27d3ef2252d2e62476389ca8f9b0cf2bbafb082a3b6bfe9d90cbcbb5529ecf7c"}, - {file = "zstandard-0.23.0-cp310-cp310-win32.whl", hash = "sha256:5d41d5e025f1e0bccae4928981e71b2334c60f580bdc8345f824e7c0a4c2a813"}, - {file = "zstandard-0.23.0-cp310-cp310-win_amd64.whl", hash = "sha256:519fbf169dfac1222a76ba8861ef4ac7f0530c35dd79ba5727014613f91613d4"}, - {file = "zstandard-0.23.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:34895a41273ad33347b2fc70e1bff4240556de3c46c6ea430a7ed91f9042aa4e"}, - {file = "zstandard-0.23.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23"}, - {file = "zstandard-0.23.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:983b6efd649723474f29ed42e1467f90a35a74793437d0bc64a5bf482bedfa0a"}, - {file = "zstandard-0.23.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80a539906390591dd39ebb8d773771dc4db82ace6372c4d41e2d293f8e32b8db"}, - {file = "zstandard-0.23.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:445e4cb5048b04e90ce96a79b4b63140e3f4ab5f662321975679b5f6360b90e2"}, - {file = "zstandard-0.23.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca"}, - {file = "zstandard-0.23.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d20fd853fbb5807c8e84c136c278827b6167ded66c72ec6f9a14b863d809211c"}, - {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ed1708dbf4d2e3a1c5c69110ba2b4eb6678262028afd6c6fbcc5a8dac9cda68e"}, - {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:be9b5b8659dff1f913039c2feee1aca499cfbc19e98fa12bc85e037c17ec6ca5"}, - {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:65308f4b4890aa12d9b6ad9f2844b7ee42c7f7a4fd3390425b242ffc57498f48"}, - {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:98da17ce9cbf3bfe4617e836d561e433f871129e3a7ac16d6ef4c680f13a839c"}, - {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8ed7d27cb56b3e058d3cf684d7200703bcae623e1dcc06ed1e18ecda39fee003"}, - {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:b69bb4f51daf461b15e7b3db033160937d3ff88303a7bc808c67bbc1eaf98c78"}, - {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:034b88913ecc1b097f528e42b539453fa82c3557e414b3de9d5632c80439a473"}, - {file = "zstandard-0.23.0-cp311-cp311-win32.whl", hash = "sha256:f2d4380bf5f62daabd7b751ea2339c1a21d1c9463f1feb7fc2bdcea2c29c3160"}, - {file = "zstandard-0.23.0-cp311-cp311-win_amd64.whl", hash = "sha256:62136da96a973bd2557f06ddd4e8e807f9e13cbb0bfb9cc06cfe6d98ea90dfe0"}, - {file = "zstandard-0.23.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b4567955a6bc1b20e9c31612e615af6b53733491aeaa19a6b3b37f3b65477094"}, - {file = "zstandard-0.23.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e172f57cd78c20f13a3415cc8dfe24bf388614324d25539146594c16d78fcc8"}, - {file = "zstandard-0.23.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0e166f698c5a3e914947388c162be2583e0c638a4703fc6a543e23a88dea3c1"}, - {file = "zstandard-0.23.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12a289832e520c6bd4dcaad68e944b86da3bad0d339ef7989fb7e88f92e96072"}, - {file = "zstandard-0.23.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d50d31bfedd53a928fed6707b15a8dbeef011bb6366297cc435accc888b27c20"}, - {file = "zstandard-0.23.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72c68dda124a1a138340fb62fa21b9bf4848437d9ca60bd35db36f2d3345f373"}, - {file = "zstandard-0.23.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53dd9d5e3d29f95acd5de6802e909ada8d8d8cfa37a3ac64836f3bc4bc5512db"}, - {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:6a41c120c3dbc0d81a8e8adc73312d668cd34acd7725f036992b1b72d22c1772"}, - {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:40b33d93c6eddf02d2c19f5773196068d875c41ca25730e8288e9b672897c105"}, - {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9206649ec587e6b02bd124fb7799b86cddec350f6f6c14bc82a2b70183e708ba"}, - {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76e79bc28a65f467e0409098fa2c4376931fd3207fbeb6b956c7c476d53746dd"}, - {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:66b689c107857eceabf2cf3d3fc699c3c0fe8ccd18df2219d978c0283e4c508a"}, - {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9c236e635582742fee16603042553d276cca506e824fa2e6489db04039521e90"}, - {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a8fffdbd9d1408006baaf02f1068d7dd1f016c6bcb7538682622c556e7b68e35"}, - {file = "zstandard-0.23.0-cp312-cp312-win32.whl", hash = "sha256:dc1d33abb8a0d754ea4763bad944fd965d3d95b5baef6b121c0c9013eaf1907d"}, - {file = "zstandard-0.23.0-cp312-cp312-win_amd64.whl", hash = "sha256:64585e1dba664dc67c7cdabd56c1e5685233fbb1fc1966cfba2a340ec0dfff7b"}, - {file = "zstandard-0.23.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:576856e8594e6649aee06ddbfc738fec6a834f7c85bf7cadd1c53d4a58186ef9"}, - {file = "zstandard-0.23.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38302b78a850ff82656beaddeb0bb989a0322a8bbb1bf1ab10c17506681d772a"}, - {file = "zstandard-0.23.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2240ddc86b74966c34554c49d00eaafa8200a18d3a5b6ffbf7da63b11d74ee2"}, - {file = "zstandard-0.23.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ef230a8fd217a2015bc91b74f6b3b7d6522ba48be29ad4ea0ca3a3775bf7dd5"}, - {file = "zstandard-0.23.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:774d45b1fac1461f48698a9d4b5fa19a69d47ece02fa469825b442263f04021f"}, - {file = "zstandard-0.23.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f77fa49079891a4aab203d0b1744acc85577ed16d767b52fc089d83faf8d8ed"}, - {file = "zstandard-0.23.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac184f87ff521f4840e6ea0b10c0ec90c6b1dcd0bad2f1e4a9a1b4fa177982ea"}, - {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c363b53e257246a954ebc7c488304b5592b9c53fbe74d03bc1c64dda153fb847"}, - {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e7792606d606c8df5277c32ccb58f29b9b8603bf83b48639b7aedf6df4fe8171"}, - {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a0817825b900fcd43ac5d05b8b3079937073d2b1ff9cf89427590718b70dd840"}, - {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9da6bc32faac9a293ddfdcb9108d4b20416219461e4ec64dfea8383cac186690"}, - {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fd7699e8fd9969f455ef2926221e0233f81a2542921471382e77a9e2f2b57f4b"}, - {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d477ed829077cd945b01fc3115edd132c47e6540ddcd96ca169facff28173057"}, - {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ce8b52c5987b3e34d5674b0ab529a4602b632ebab0a93b07bfb4dfc8f8a33"}, - {file = "zstandard-0.23.0-cp313-cp313-win32.whl", hash = "sha256:a9b07268d0c3ca5c170a385a0ab9fb7fdd9f5fd866be004c4ea39e44edce47dd"}, - {file = "zstandard-0.23.0-cp313-cp313-win_amd64.whl", hash = "sha256:f3513916e8c645d0610815c257cbfd3242adfd5c4cfa78be514e5a3ebb42a41b"}, - {file = "zstandard-0.23.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2ef3775758346d9ac6214123887d25c7061c92afe1f2b354f9388e9e4d48acfc"}, - {file = "zstandard-0.23.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4051e406288b8cdbb993798b9a45c59a4896b6ecee2f875424ec10276a895740"}, - {file = "zstandard-0.23.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2d1a054f8f0a191004675755448d12be47fa9bebbcffa3cdf01db19f2d30a54"}, - {file = "zstandard-0.23.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f83fa6cae3fff8e98691248c9320356971b59678a17f20656a9e59cd32cee6d8"}, - {file = "zstandard-0.23.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:32ba3b5ccde2d581b1e6aa952c836a6291e8435d788f656fe5976445865ae045"}, - {file = "zstandard-0.23.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f146f50723defec2975fb7e388ae3a024eb7151542d1599527ec2aa9cacb152"}, - {file = "zstandard-0.23.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1bfe8de1da6d104f15a60d4a8a768288f66aa953bbe00d027398b93fb9680b26"}, - {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:29a2bc7c1b09b0af938b7a8343174b987ae021705acabcbae560166567f5a8db"}, - {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:61f89436cbfede4bc4e91b4397eaa3e2108ebe96d05e93d6ccc95ab5714be512"}, - {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:53ea7cdc96c6eb56e76bb06894bcfb5dfa93b7adcf59d61c6b92674e24e2dd5e"}, - {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:a4ae99c57668ca1e78597d8b06d5af837f377f340f4cce993b551b2d7731778d"}, - {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:379b378ae694ba78cef921581ebd420c938936a153ded602c4fea612b7eaa90d"}, - {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:50a80baba0285386f97ea36239855f6020ce452456605f262b2d33ac35c7770b"}, - {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:61062387ad820c654b6a6b5f0b94484fa19515e0c5116faf29f41a6bc91ded6e"}, - {file = "zstandard-0.23.0-cp38-cp38-win32.whl", hash = "sha256:b8c0bd73aeac689beacd4e7667d48c299f61b959475cdbb91e7d3d88d27c56b9"}, - {file = "zstandard-0.23.0-cp38-cp38-win_amd64.whl", hash = "sha256:a05e6d6218461eb1b4771d973728f0133b2a4613a6779995df557f70794fd60f"}, - {file = "zstandard-0.23.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3aa014d55c3af933c1315eb4bb06dd0459661cc0b15cd61077afa6489bec63bb"}, - {file = "zstandard-0.23.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a7f0804bb3799414af278e9ad51be25edf67f78f916e08afdb983e74161b916"}, - {file = "zstandard-0.23.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb2b1ecfef1e67897d336de3a0e3f52478182d6a47eda86cbd42504c5cbd009a"}, - {file = "zstandard-0.23.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:837bb6764be6919963ef41235fd56a6486b132ea64afe5fafb4cb279ac44f259"}, - {file = "zstandard-0.23.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1516c8c37d3a053b01c1c15b182f3b5f5eef19ced9b930b684a73bad121addf4"}, - {file = "zstandard-0.23.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48ef6a43b1846f6025dde6ed9fee0c24e1149c1c25f7fb0a0585572b2f3adc58"}, - {file = "zstandard-0.23.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11e3bf3c924853a2d5835b24f03eeba7fc9b07d8ca499e247e06ff5676461a15"}, - {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2fb4535137de7e244c230e24f9d1ec194f61721c86ebea04e1581d9d06ea1269"}, - {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8c24f21fa2af4bb9f2c492a86fe0c34e6d2c63812a839590edaf177b7398f700"}, - {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a8c86881813a78a6f4508ef9daf9d4995b8ac2d147dcb1a450448941398091c9"}, - {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fe3b385d996ee0822fd46528d9f0443b880d4d05528fd26a9119a54ec3f91c69"}, - {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:82d17e94d735c99621bf8ebf9995f870a6b3e6d14543b99e201ae046dfe7de70"}, - {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c7c517d74bea1a6afd39aa612fa025e6b8011982a0897768a2f7c8ab4ebb78a2"}, - {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fd7e0f1cfb70eb2f95a19b472ee7ad6d9a0a992ec0ae53286870c104ca939e5"}, - {file = "zstandard-0.23.0-cp39-cp39-win32.whl", hash = "sha256:43da0f0092281bf501f9c5f6f3b4c975a8a0ea82de49ba3f7100e64d422a1274"}, - {file = "zstandard-0.23.0-cp39-cp39-win_amd64.whl", hash = "sha256:f8346bfa098532bc1fb6c7ef06783e969d87a99dd1d2a5a18a892c1d7a643c58"}, - {file = "zstandard-0.23.0.tar.gz", hash = "sha256:b2d8c62d08e7255f68f7a740bae85b3c9b8e5466baa9cbf7f57f1cde0ac6bc09"}, -] - -[package.dependencies] -cffi = {version = ">=1.11", markers = "platform_python_implementation == \"PyPy\""} - -[package.extras] -cffi = ["cffi (>=1.11)"] - -[extras] -aws = ["langchain-aws"] -elasticsearch = ["elasticsearch"] -gmail = ["google-api-core", "google-api-python-client", "google-auth", "google-auth-httplib2", "google-auth-oauthlib", "requests"] -google = ["google-generativeai"] -googledrive = ["google-api-python-client", "google-auth-httplib2", "google-auth-oauthlib"] -lancedb = ["lancedb"] -llama2 = ["replicate"] -milvus = ["pymilvus"] -mistralai = ["langchain-mistralai"] -mysql = ["mysql-connector-python"] -opensearch = ["opensearch-py"] -opensource = ["gpt4all", "sentence-transformers", "torch"] -postgres = ["psycopg", "psycopg-binary", "psycopg-pool"] -qdrant = ["qdrant-client"] -together = ["together"] -vertexai = ["langchain-google-vertexai"] -weaviate = ["weaviate-client"] - -[metadata] -lock-version = "2.1" -python-versions = ">=3.9,<=3.13.2" -content-hash = "2853314a806fa8337c1a0b2e0d61e444ba21605be7b3491b48a56ecf14c48b86" diff --git a/embedchain/poetry.toml b/embedchain/poetry.toml deleted file mode 100644 index 8eb0c8019..000000000 --- a/embedchain/poetry.toml +++ /dev/null @@ -1,3 +0,0 @@ -[virtualenvs] -in-project = true -path = "." \ No newline at end of file diff --git a/embedchain/pyproject.toml b/embedchain/pyproject.toml deleted file mode 100644 index b9a1ad5b1..000000000 --- a/embedchain/pyproject.toml +++ /dev/null @@ -1,189 +0,0 @@ -[tool.poetry] -name = "embedchain" -version = "0.1.128" -description = "Simplest open source retrieval (RAG) framework" -authors = [ - "Taranjeet Singh ", - "Deshraj Yadav ", -] -license = "Apache License" -readme = "README.md" -exclude = [ - "db", - "configs", - "notebooks" -] -packages = [ - { include = "embedchain" }, -] - -[build-system] -build-backend = "poetry.core.masonry.api" -requires = ["poetry-core"] - -[tool.ruff] -line-length = 120 -exclude = [ - ".bzr", - ".direnv", - ".eggs", - ".git", - ".git-rewrite", - ".hg", - ".mypy_cache", - ".nox", - ".pants.d", - ".pytype", - ".ruff_cache", - ".svn", - ".tox", - ".venv", - "__pypackages__", - "_build", - "buck-out", - "build", - "dist", - "node_modules", - "venv" -] -target-version = "py38" - -[tool.ruff.lint] -select = ["ASYNC", "E", "F"] -ignore = [] -fixable = ["ALL"] -unfixable = [] -dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" - -# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`. -[tool.ruff.lint.per-file-ignores] -"embedchain/__init__.py" = ["E401"] - -[tool.ruff.lint.mccabe] -max-complexity = 10 - -[tool.black] -line-length = 120 -target-version = ["py38", "py39", "py310", "py311"] -include = '\.pyi?$' -exclude = ''' -/( - \.eggs - | \.git - | \.hg - | \.mypy_cache - | \.nox - | \.pants.d - | \.pytype - | \.ruff_cache - | \.svn - | \.tox - | \.venv - | __pypackages__ - | _build - | buck-out - | build - | dist - | node_modules - | venv -)/ -''' - -[tool.black.format] -color = true - -[tool.poetry.dependencies] -python = ">=3.9,<=3.13.2" -python-dotenv = "^1.0.0" -langchain = "^0.3.1" -requests = "^2.31.0" -openai = ">=1.1.1" -chromadb = "^0.5.10" -posthog = "^3.0.2" -rich = "^13.7.0" -beautifulsoup4 = "^4.12.2" -pypdf = "^5.0.0" -gptcache = "^0.1.43" -pysbd = "^0.3.4" -mem0ai = "^0.1.54" -tiktoken = { version = "^0.7.0", optional = true } -sentence-transformers = { version = "^2.2.2", optional = true } -torch = { version = ">=2.6.0,<3", optional = true } -# Torch 2.0.1 is not compatible with poetry (https://github.com/pytorch/pytorch/issues/100974) -gpt4all = { version = "2.0.2", optional = true } -# 1.0.9 is not working for some users (https://github.com/nomic-ai/gpt4all/issues/1394) -opensearch-py = { version = "2.3.1", optional = true } -elasticsearch = { version = "^8.9.0", optional = true } -cohere = { version = "^5.3", optional = true } -together = { version = "^1.2.1", optional = true } -lancedb = { version = "^0.6.2", optional = true } -weaviate-client = { version = "^3.24.1", optional = true } -qdrant-client = { version = "^1.6.3", optional = true } -pymilvus = { version = "2.4.3", optional = true } -google-cloud-aiplatform = { version = "^1.26.1", optional = true } -replicate = { version = "^0.15.4", optional = true } -schema = "^0.7.5" -psycopg = { version = "^3.1.12", optional = true } -psycopg-binary = { version = "^3.1.12", optional = true } -psycopg-pool = { version = "^3.1.8", optional = true } -mysql-connector-python = { version = "^8.1.0", optional = true } -google-generativeai = { version = "^0.3.0", optional = true } -google-api-python-client = { version = "^2.111.0", optional = true } -google-auth-oauthlib = { version = "^1.2.0", optional = true } -google-auth = { version = "^2.25.2", optional = true } -google-auth-httplib2 = { version = "^0.2.0", optional = true } -google-api-core = { version = "^2.15.0", optional = true } -langchain-mistralai = { version = "^0.2.0", optional = true } -langchain-openai = "^0.2.1" -langchain-google-vertexai = { version = "^2.0.2", optional = true } -sqlalchemy = "^2.0.27" -alembic = "^1.13.1" -langchain-cohere = "^0.3.0" -langchain-community = "^0.3.1" -langchain-aws = {version = "^0.2.1", optional = true} -langsmith = "^0.3.18" - -[tool.poetry.group.dev.dependencies] -black = "^23.3.0" -pre-commit = "^3.2.2" -ruff = "^0.1.11" -pytest = "^7.3.1" -pytest-mock = "^3.10.0" -pytest-env = "^0.8.1" -click = "^8.1.3" -isort = "^5.12.0" -pytest-cov = "^4.1.0" -responses = "^0.23.3" -mock = "^5.1.0" -pytest-asyncio = "^0.21.1" - -[tool.poetry.extras] -opensource = ["sentence-transformers", "torch", "gpt4all"] -lancedb = ["lancedb"] -elasticsearch = ["elasticsearch"] -opensearch = ["opensearch-py"] -weaviate = ["weaviate-client"] -qdrant = ["qdrant-client"] -together = ["together"] -milvus = ["pymilvus"] -vertexai = ["langchain-google-vertexai"] -llama2 = ["replicate"] -gmail = [ - "requests", - "google-api-python-client", - "google-auth", - "google-auth-oauthlib", - "google-auth-httplib2", - "google-api-core", -] -googledrive = ["google-api-python-client", "google-auth-oauthlib", "google-auth-httplib2"] -postgres = ["psycopg", "psycopg-binary", "psycopg-pool"] -mysql = ["mysql-connector-python"] -google = ["google-generativeai"] -mistralai = ["langchain-mistralai"] -aws = ["langchain-aws"] - -[tool.poetry.group.docs.dependencies] - -[tool.poetry.scripts] -ec = "embedchain.cli:cli" \ No newline at end of file diff --git a/embedchain/tests/__init__.py b/embedchain/tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/embedchain/tests/chunkers/test_base_chunker.py b/embedchain/tests/chunkers/test_base_chunker.py deleted file mode 100644 index 23cf1e8ce..000000000 --- a/embedchain/tests/chunkers/test_base_chunker.py +++ /dev/null @@ -1,99 +0,0 @@ -import hashlib -from unittest.mock import MagicMock - -import pytest - -from embedchain.chunkers.base_chunker import BaseChunker -from embedchain.config.add_config import ChunkerConfig -from embedchain.models.data_type import DataType - - -@pytest.fixture -def text_splitter_mock(): - return MagicMock() - - -@pytest.fixture -def loader_mock(): - return MagicMock() - - -@pytest.fixture -def app_id(): - return "test_app" - - -@pytest.fixture -def data_type(): - return DataType.TEXT - - -@pytest.fixture -def chunker(text_splitter_mock, data_type): - text_splitter = text_splitter_mock - chunker = BaseChunker(text_splitter) - chunker.set_data_type(data_type) - return chunker - - -def test_create_chunks_with_config(chunker, text_splitter_mock, loader_mock, app_id, data_type): - text_splitter_mock.split_text.return_value = ["Chunk 1", "long chunk"] - loader_mock.load_data.return_value = { - "data": [{"content": "Content 1", "meta_data": {"url": "URL 1"}}], - "doc_id": "DocID", - } - config = ChunkerConfig(chunk_size=50, chunk_overlap=0, length_function=len, min_chunk_size=10) - result = chunker.create_chunks(loader_mock, "test_src", app_id, config) - - assert result["documents"] == ["long chunk"] - - -def test_create_chunks(chunker, text_splitter_mock, loader_mock, app_id, data_type): - text_splitter_mock.split_text.return_value = ["Chunk 1", "Chunk 2"] - loader_mock.load_data.return_value = { - "data": [{"content": "Content 1", "meta_data": {"url": "URL 1"}}], - "doc_id": "DocID", - } - - result = chunker.create_chunks(loader_mock, "test_src", app_id) - expected_ids = [ - f"{app_id}--" + hashlib.sha256(("Chunk 1" + "URL 1").encode()).hexdigest(), - f"{app_id}--" + hashlib.sha256(("Chunk 2" + "URL 1").encode()).hexdigest(), - ] - - assert result["documents"] == ["Chunk 1", "Chunk 2"] - assert result["ids"] == expected_ids - assert result["metadatas"] == [ - { - "url": "URL 1", - "data_type": data_type.value, - "doc_id": f"{app_id}--DocID", - }, - { - "url": "URL 1", - "data_type": data_type.value, - "doc_id": f"{app_id}--DocID", - }, - ] - assert result["doc_id"] == f"{app_id}--DocID" - - -def test_get_chunks(chunker, text_splitter_mock): - text_splitter_mock.split_text.return_value = ["Chunk 1", "Chunk 2"] - - content = "This is a test content." - result = chunker.get_chunks(content) - - assert len(result) == 2 - assert result == ["Chunk 1", "Chunk 2"] - - -def test_set_data_type(chunker): - chunker.set_data_type(DataType.MDX) - assert chunker.data_type == DataType.MDX - - -def test_get_word_count(chunker): - documents = ["This is a test.", "Another test."] - result = chunker.get_word_count(documents) - assert result == 6 diff --git a/embedchain/tests/chunkers/test_chunkers.py b/embedchain/tests/chunkers/test_chunkers.py deleted file mode 100644 index 8258e7764..000000000 --- a/embedchain/tests/chunkers/test_chunkers.py +++ /dev/null @@ -1,66 +0,0 @@ -from embedchain.chunkers.audio import AudioChunker -from embedchain.chunkers.common_chunker import CommonChunker -from embedchain.chunkers.discourse import DiscourseChunker -from embedchain.chunkers.docs_site import DocsSiteChunker -from embedchain.chunkers.docx_file import DocxFileChunker -from embedchain.chunkers.excel_file import ExcelFileChunker -from embedchain.chunkers.gmail import GmailChunker -from embedchain.chunkers.google_drive import GoogleDriveChunker -from embedchain.chunkers.json import JSONChunker -from embedchain.chunkers.mdx import MdxChunker -from embedchain.chunkers.notion import NotionChunker -from embedchain.chunkers.openapi import OpenAPIChunker -from embedchain.chunkers.pdf_file import PdfFileChunker -from embedchain.chunkers.postgres import PostgresChunker -from embedchain.chunkers.qna_pair import QnaPairChunker -from embedchain.chunkers.sitemap import SitemapChunker -from embedchain.chunkers.slack import SlackChunker -from embedchain.chunkers.table import TableChunker -from embedchain.chunkers.text import TextChunker -from embedchain.chunkers.web_page import WebPageChunker -from embedchain.chunkers.xml import XmlChunker -from embedchain.chunkers.youtube_video import YoutubeVideoChunker -from embedchain.config.add_config import ChunkerConfig - -chunker_config = ChunkerConfig(chunk_size=500, chunk_overlap=0, length_function=len) - -chunker_common_config = { - DocsSiteChunker: {"chunk_size": 500, "chunk_overlap": 50, "length_function": len}, - DocxFileChunker: {"chunk_size": 1000, "chunk_overlap": 0, "length_function": len}, - PdfFileChunker: {"chunk_size": 1000, "chunk_overlap": 0, "length_function": len}, - TextChunker: {"chunk_size": 300, "chunk_overlap": 0, "length_function": len}, - MdxChunker: {"chunk_size": 1000, "chunk_overlap": 0, "length_function": len}, - NotionChunker: {"chunk_size": 300, "chunk_overlap": 0, "length_function": len}, - QnaPairChunker: {"chunk_size": 300, "chunk_overlap": 0, "length_function": len}, - TableChunker: {"chunk_size": 300, "chunk_overlap": 0, "length_function": len}, - SitemapChunker: {"chunk_size": 500, "chunk_overlap": 0, "length_function": len}, - WebPageChunker: {"chunk_size": 2000, "chunk_overlap": 0, "length_function": len}, - XmlChunker: {"chunk_size": 500, "chunk_overlap": 50, "length_function": len}, - YoutubeVideoChunker: {"chunk_size": 2000, "chunk_overlap": 0, "length_function": len}, - JSONChunker: {"chunk_size": 1000, "chunk_overlap": 0, "length_function": len}, - OpenAPIChunker: {"chunk_size": 1000, "chunk_overlap": 0, "length_function": len}, - GmailChunker: {"chunk_size": 1000, "chunk_overlap": 0, "length_function": len}, - PostgresChunker: {"chunk_size": 1000, "chunk_overlap": 0, "length_function": len}, - SlackChunker: {"chunk_size": 1000, "chunk_overlap": 0, "length_function": len}, - DiscourseChunker: {"chunk_size": 1000, "chunk_overlap": 0, "length_function": len}, - CommonChunker: {"chunk_size": 2000, "chunk_overlap": 0, "length_function": len}, - GoogleDriveChunker: {"chunk_size": 1000, "chunk_overlap": 0, "length_function": len}, - ExcelFileChunker: {"chunk_size": 1000, "chunk_overlap": 0, "length_function": len}, - AudioChunker: {"chunk_size": 1000, "chunk_overlap": 0, "length_function": len}, -} - - -def test_default_config_values(): - for chunker_class, config in chunker_common_config.items(): - chunker = chunker_class() - assert chunker.text_splitter._chunk_size == config["chunk_size"] - assert chunker.text_splitter._chunk_overlap == config["chunk_overlap"] - assert chunker.text_splitter._length_function == config["length_function"] - - -def test_custom_config_values(): - for chunker_class, _ in chunker_common_config.items(): - chunker = chunker_class(config=chunker_config) - assert chunker.text_splitter._chunk_size == 500 - assert chunker.text_splitter._chunk_overlap == 0 - assert chunker.text_splitter._length_function == len diff --git a/embedchain/tests/chunkers/test_text.py b/embedchain/tests/chunkers/test_text.py deleted file mode 100644 index 9a2873572..000000000 --- a/embedchain/tests/chunkers/test_text.py +++ /dev/null @@ -1,86 +0,0 @@ -# ruff: noqa: E501 - -from embedchain.chunkers.text import TextChunker -from embedchain.config import ChunkerConfig -from embedchain.models.data_type import DataType - - -class TestTextChunker: - def test_chunks_without_app_id(self): - """ - Test the chunks generated by TextChunker. - """ - chunker_config = ChunkerConfig(chunk_size=10, chunk_overlap=0, length_function=len, min_chunk_size=0) - chunker = TextChunker(config=chunker_config) - text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - # Data type must be set manually in the test - chunker.set_data_type(DataType.TEXT) - result = chunker.create_chunks(MockLoader(), text, chunker_config) - documents = result["documents"] - assert len(documents) > 5 - - def test_chunks_with_app_id(self): - """ - Test the chunks generated by TextChunker with app_id - """ - chunker_config = ChunkerConfig(chunk_size=10, chunk_overlap=0, length_function=len, min_chunk_size=0) - chunker = TextChunker(config=chunker_config) - text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - chunker.set_data_type(DataType.TEXT) - result = chunker.create_chunks(MockLoader(), text, chunker_config) - documents = result["documents"] - assert len(documents) > 5 - - def test_big_chunksize(self): - """ - Test that if an infinitely high chunk size is used, only one chunk is returned. - """ - chunker_config = ChunkerConfig(chunk_size=9999999999, chunk_overlap=0, length_function=len, min_chunk_size=0) - chunker = TextChunker(config=chunker_config) - text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - # Data type must be set manually in the test - chunker.set_data_type(DataType.TEXT) - result = chunker.create_chunks(MockLoader(), text, chunker_config) - documents = result["documents"] - assert len(documents) == 1 - - def test_small_chunksize(self): - """ - Test that if a chunk size of one is used, every character is a chunk. - """ - chunker_config = ChunkerConfig(chunk_size=1, chunk_overlap=0, length_function=len, min_chunk_size=0) - chunker = TextChunker(config=chunker_config) - # We can't test with lorem ipsum because chunks are deduped, so would be recurring characters. - text = """0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c""" - # Data type must be set manually in the test - chunker.set_data_type(DataType.TEXT) - result = chunker.create_chunks(MockLoader(), text, chunker_config) - documents = result["documents"] - assert len(documents) == len(text) - - def test_word_count(self): - chunker_config = ChunkerConfig(chunk_size=1, chunk_overlap=0, length_function=len, min_chunk_size=0) - chunker = TextChunker(config=chunker_config) - chunker.set_data_type(DataType.TEXT) - - document = ["ab cd", "ef gh"] - result = chunker.get_word_count(document) - assert result == 4 - - -class MockLoader: - @staticmethod - def load_data(src) -> dict: - """ - Mock loader that returns a list of data dictionaries. - Adjust this method to return different data for testing. - """ - return { - "doc_id": "123", - "data": [ - { - "content": src, - "meta_data": {"url": "none"}, - } - ], - } diff --git a/embedchain/tests/conftest.py b/embedchain/tests/conftest.py deleted file mode 100644 index 0b5807a0d..000000000 --- a/embedchain/tests/conftest.py +++ /dev/null @@ -1,35 +0,0 @@ -import os - -import pytest -from sqlalchemy import MetaData, create_engine -from sqlalchemy.orm import sessionmaker - - -@pytest.fixture(autouse=True) -def clean_db(): - db_path = os.path.expanduser("~/.embedchain/embedchain.db") - db_url = f"sqlite:///{db_path}" - engine = create_engine(db_url) - metadata = MetaData() - metadata.reflect(bind=engine) # Reflect schema from the engine - Session = sessionmaker(bind=engine) - session = Session() - - try: - # Iterate over all tables in reversed order to respect foreign keys - for table in reversed(metadata.sorted_tables): - if table.name != "alembic_version": # Skip the Alembic version table - session.execute(table.delete()) - session.commit() - except Exception as e: - session.rollback() - print(f"Error cleaning database: {e}") - finally: - session.close() - - -@pytest.fixture(autouse=True) -def disable_telemetry(): - os.environ["EC_TELEMETRY"] = "false" - yield - del os.environ["EC_TELEMETRY"] \ No newline at end of file diff --git a/embedchain/tests/embedchain/test_add.py b/embedchain/tests/embedchain/test_add.py deleted file mode 100644 index b9d8437a9..000000000 --- a/embedchain/tests/embedchain/test_add.py +++ /dev/null @@ -1,52 +0,0 @@ -import os - -import pytest - -from embedchain import App -from embedchain.config import AddConfig, AppConfig, ChunkerConfig -from embedchain.models.data_type import DataType - -os.environ["OPENAI_API_KEY"] = "test_key" - - -@pytest.fixture -def app(mocker): - mocker.patch("chromadb.api.models.Collection.Collection.add") - return App(config=AppConfig(collect_metrics=False)) - - -def test_add(app): - app.add("https://example.com", metadata={"foo": "bar"}) - assert app.user_asks == [["https://example.com", "web_page", {"foo": "bar"}]] - - -# TODO: Make this test faster by generating a sitemap locally rather than using a remote one -# def test_add_sitemap(app): -# app.add("https://www.google.com/sitemap.xml", metadata={"foo": "bar"}) -# assert app.user_asks == [["https://www.google.com/sitemap.xml", "sitemap", {"foo": "bar"}]] - - -def test_add_forced_type(app): - data_type = "text" - app.add("https://example.com", data_type=data_type, metadata={"foo": "bar"}) - assert app.user_asks == [["https://example.com", data_type, {"foo": "bar"}]] - - -def test_dry_run(app): - chunker_config = ChunkerConfig(chunk_size=1, chunk_overlap=0, min_chunk_size=0) - text = """0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ""" - - result = app.add(source=text, config=AddConfig(chunker=chunker_config), dry_run=True) - - chunks = result["chunks"] - metadata = result["metadata"] - count = result["count"] - data_type = result["type"] - - assert len(chunks) == len(text) - assert count == len(text) - assert data_type == DataType.TEXT - for item in metadata: - assert isinstance(item, dict) - assert "local" in item["url"] - assert "text" in item["data_type"] diff --git a/embedchain/tests/embedchain/test_embedchain.py b/embedchain/tests/embedchain/test_embedchain.py deleted file mode 100644 index 7614b8deb..000000000 --- a/embedchain/tests/embedchain/test_embedchain.py +++ /dev/null @@ -1,75 +0,0 @@ -import os - -import pytest -from chromadb.api.models.Collection import Collection - -from embedchain import App -from embedchain.config import AppConfig, ChromaDbConfig -from embedchain.embedchain import EmbedChain -from embedchain.llm.base import BaseLlm -from embedchain.memory.base import ChatHistory -from embedchain.vectordb.chroma import ChromaDB - -os.environ["OPENAI_API_KEY"] = "test-api-key" - - -@pytest.fixture -def app_instance(): - config = AppConfig(log_level="DEBUG", collect_metrics=False) - return App(config=config) - - -def test_whole_app(app_instance, mocker): - knowledge = "lorem ipsum dolor sit amet, consectetur adipiscing" - - mocker.patch.object(EmbedChain, "add") - mocker.patch.object(EmbedChain, "_retrieve_from_database") - mocker.patch.object(BaseLlm, "get_answer_from_llm", return_value=knowledge) - mocker.patch.object(BaseLlm, "get_llm_model_answer", return_value=knowledge) - mocker.patch.object(BaseLlm, "generate_prompt") - mocker.patch.object(BaseLlm, "add_history") - mocker.patch.object(ChatHistory, "delete", autospec=True) - - app_instance.add(knowledge, data_type="text") - app_instance.query("What text did I give you?") - app_instance.chat("What text did I give you?") - - assert BaseLlm.generate_prompt.call_count == 2 - app_instance.reset() - - -def test_add_after_reset(app_instance, mocker): - mocker.patch("embedchain.vectordb.chroma.chromadb.Client") - - config = AppConfig(log_level="DEBUG", collect_metrics=False) - chroma_config = ChromaDbConfig(allow_reset=True) - db = ChromaDB(config=chroma_config) - app_instance = App(config=config, db=db) - - # mock delete chat history - mocker.patch.object(ChatHistory, "delete", autospec=True) - - app_instance.reset() - - app_instance.db.client.heartbeat() - - mocker.patch.object(Collection, "add") - - app_instance.db.collection.add( - embeddings=[[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2]], - metadatas=[ - {"chapter": "3", "verse": "16"}, - {"chapter": "3", "verse": "5"}, - {"chapter": "29", "verse": "11"}, - ], - ids=["id1", "id2", "id3"], - ) - - app_instance.reset() - - -def test_add_with_incorrect_content(app_instance, mocker): - content = [{"foo": "bar"}] - - with pytest.raises(TypeError): - app_instance.add(content, data_type="json") diff --git a/embedchain/tests/embedchain/test_utils.py b/embedchain/tests/embedchain/test_utils.py deleted file mode 100644 index 22806b79f..000000000 --- a/embedchain/tests/embedchain/test_utils.py +++ /dev/null @@ -1,133 +0,0 @@ -import tempfile -import unittest -from unittest.mock import patch - -from embedchain.models.data_type import DataType -from embedchain.utils.misc import detect_datatype - - -class TestApp(unittest.TestCase): - """Test that the datatype detection is working, based on the input.""" - - def test_detect_datatype_youtube(self): - self.assertEqual(detect_datatype("https://www.youtube.com/watch?v=dQw4w9WgXcQ"), DataType.YOUTUBE_VIDEO) - self.assertEqual(detect_datatype("https://m.youtube.com/watch?v=dQw4w9WgXcQ"), DataType.YOUTUBE_VIDEO) - self.assertEqual( - detect_datatype("https://www.youtube-nocookie.com/watch?v=dQw4w9WgXcQ"), DataType.YOUTUBE_VIDEO - ) - self.assertEqual(detect_datatype("https://vid.plus/watch?v=dQw4w9WgXcQ"), DataType.YOUTUBE_VIDEO) - self.assertEqual(detect_datatype("https://youtu.be/dQw4w9WgXcQ"), DataType.YOUTUBE_VIDEO) - - def test_detect_datatype_local_file(self): - self.assertEqual(detect_datatype("file:///home/user/file.txt"), DataType.WEB_PAGE) - - def test_detect_datatype_pdf(self): - self.assertEqual(detect_datatype("https://www.example.com/document.pdf"), DataType.PDF_FILE) - - def test_detect_datatype_local_pdf(self): - self.assertEqual(detect_datatype("file:///home/user/document.pdf"), DataType.PDF_FILE) - - def test_detect_datatype_xml(self): - self.assertEqual(detect_datatype("https://www.example.com/sitemap.xml"), DataType.SITEMAP) - - def test_detect_datatype_local_xml(self): - self.assertEqual(detect_datatype("file:///home/user/sitemap.xml"), DataType.SITEMAP) - - def test_detect_datatype_docx(self): - self.assertEqual(detect_datatype("https://www.example.com/document.docx"), DataType.DOCX) - - def test_detect_datatype_local_docx(self): - self.assertEqual(detect_datatype("file:///home/user/document.docx"), DataType.DOCX) - - def test_detect_data_type_json(self): - self.assertEqual(detect_datatype("https://www.example.com/data.json"), DataType.JSON) - - def test_detect_data_type_local_json(self): - self.assertEqual(detect_datatype("file:///home/user/data.json"), DataType.JSON) - - @patch("os.path.isfile") - def test_detect_datatype_regular_filesystem_docx(self, mock_isfile): - with tempfile.NamedTemporaryFile(suffix=".docx", delete=True) as tmp: - mock_isfile.return_value = True - self.assertEqual(detect_datatype(tmp.name), DataType.DOCX) - - def test_detect_datatype_docs_site(self): - self.assertEqual(detect_datatype("https://docs.example.com"), DataType.DOCS_SITE) - - def test_detect_datatype_docs_sitein_path(self): - self.assertEqual(detect_datatype("https://www.example.com/docs/index.html"), DataType.DOCS_SITE) - self.assertNotEqual(detect_datatype("file:///var/www/docs/index.html"), DataType.DOCS_SITE) # NOT equal - - def test_detect_datatype_web_page(self): - self.assertEqual(detect_datatype("https://nav.al/agi"), DataType.WEB_PAGE) - - def test_detect_datatype_invalid_url(self): - self.assertEqual(detect_datatype("not a url"), DataType.TEXT) - - def test_detect_datatype_qna_pair(self): - self.assertEqual( - detect_datatype(("Question?", "Answer. Content of the string is irrelevant.")), DataType.QNA_PAIR - ) # - - def test_detect_datatype_qna_pair_types(self): - """Test that a QnA pair needs to be a tuple of length two, and both items have to be strings.""" - with self.assertRaises(TypeError): - self.assertNotEqual( - detect_datatype(("How many planets are in our solar system?", 8)), DataType.QNA_PAIR - ) # NOT equal - - def test_detect_datatype_text(self): - self.assertEqual(detect_datatype("Just some text."), DataType.TEXT) - - def test_detect_datatype_non_string_error(self): - """Test type error if the value passed is not a string, and not a valid non-string data_type""" - with self.assertRaises(TypeError): - detect_datatype(["foo", "bar"]) - - @patch("os.path.isfile") - def test_detect_datatype_regular_filesystem_file_txt(self, mock_isfile): - with tempfile.NamedTemporaryFile(suffix=".txt", delete=True) as tmp: - mock_isfile.return_value = True - self.assertEqual(detect_datatype(tmp.name), DataType.TEXT_FILE) - - def test_detect_datatype_regular_filesystem_no_file(self): - """Test that if a filepath is not actually an existing file, it is not handled as a file path.""" - self.assertEqual(detect_datatype("/var/not-an-existing-file.txt"), DataType.TEXT) - - def test_doc_examples_quickstart(self): - """Test examples used in the documentation.""" - self.assertEqual(detect_datatype("https://en.wikipedia.org/wiki/Elon_Musk"), DataType.WEB_PAGE) - self.assertEqual(detect_datatype("https://www.tesla.com/elon-musk"), DataType.WEB_PAGE) - - def test_doc_examples_introduction(self): - """Test examples used in the documentation.""" - self.assertEqual(detect_datatype("https://www.youtube.com/watch?v=3qHkcs3kG44"), DataType.YOUTUBE_VIDEO) - self.assertEqual( - detect_datatype( - "https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf" - ), - DataType.PDF_FILE, - ) - self.assertEqual(detect_datatype("https://nav.al/feedback"), DataType.WEB_PAGE) - - def test_doc_examples_app_types(self): - """Test examples used in the documentation.""" - self.assertEqual(detect_datatype("https://www.youtube.com/watch?v=Ff4fRgnuFgQ"), DataType.YOUTUBE_VIDEO) - self.assertEqual(detect_datatype("https://en.wikipedia.org/wiki/Mark_Zuckerberg"), DataType.WEB_PAGE) - - def test_doc_examples_configuration(self): - """Test examples used in the documentation.""" - import subprocess - import sys - - subprocess.check_call([sys.executable, "-m", "pip", "install", "wikipedia"]) - import wikipedia - - page = wikipedia.page("Albert Einstein") - # TODO: Add a wikipedia type, so wikipedia is a dependency and we don't need this slow test. - # (timings: import: 1.4s, fetch wiki: 0.7s) - self.assertEqual(detect_datatype(page.content), DataType.TEXT) - - -if __name__ == "__main__": - unittest.main() diff --git a/embedchain/tests/embedder/test_aws_bedrock_embedder.py b/embedchain/tests/embedder/test_aws_bedrock_embedder.py deleted file mode 100644 index f22b445b2..000000000 --- a/embedchain/tests/embedder/test_aws_bedrock_embedder.py +++ /dev/null @@ -1,21 +0,0 @@ -from unittest.mock import patch - -from embedchain.config.embedder.aws_bedrock import AWSBedrockEmbedderConfig -from embedchain.embedder.aws_bedrock import AWSBedrockEmbedder - - -def test_aws_bedrock_embedder_with_model(): - config = AWSBedrockEmbedderConfig( - model="test-model", - model_kwargs={"param": "value"}, - vector_dimension=1536, - ) - with patch("embedchain.embedder.aws_bedrock.BedrockEmbeddings") as mock_embeddings: - embedder = AWSBedrockEmbedder(config=config) - assert embedder.config.model == "test-model" - assert embedder.config.model_kwargs == {"param": "value"} - assert embedder.config.vector_dimension == 1536 - mock_embeddings.assert_called_once_with( - model_id="test-model", - model_kwargs={"param": "value"}, - ) diff --git a/embedchain/tests/embedder/test_azure_openai_embedder.py b/embedchain/tests/embedder/test_azure_openai_embedder.py deleted file mode 100644 index 2667d01f3..000000000 --- a/embedchain/tests/embedder/test_azure_openai_embedder.py +++ /dev/null @@ -1,52 +0,0 @@ -from unittest.mock import Mock, patch - -import httpx - -from embedchain.config import BaseEmbedderConfig -from embedchain.embedder.azure_openai import AzureOpenAIEmbedder - - -def test_azure_openai_embedder_with_http_client(monkeypatch): - mock_http_client = Mock(spec=httpx.Client) - mock_http_client_instance = Mock(spec=httpx.Client) - mock_http_client.return_value = mock_http_client_instance - - with patch("embedchain.embedder.azure_openai.AzureOpenAIEmbeddings") as mock_embeddings, patch( - "httpx.Client", new=mock_http_client - ) as mock_http_client: - config = BaseEmbedderConfig( - deployment_name="text-embedding-ada-002", - http_client_proxies="http://testproxy.mem0.net:8000", - ) - - _ = AzureOpenAIEmbedder(config=config) - - mock_embeddings.assert_called_once_with( - deployment="text-embedding-ada-002", - http_client=mock_http_client_instance, - http_async_client=None, - ) - mock_http_client.assert_called_once_with(proxies="http://testproxy.mem0.net:8000") - - -def test_azure_openai_embedder_with_http_async_client(monkeypatch): - mock_http_async_client = Mock(spec=httpx.AsyncClient) - mock_http_async_client_instance = Mock(spec=httpx.AsyncClient) - mock_http_async_client.return_value = mock_http_async_client_instance - - with patch("embedchain.embedder.azure_openai.AzureOpenAIEmbeddings") as mock_embeddings, patch( - "httpx.AsyncClient", new=mock_http_async_client - ) as mock_http_async_client: - config = BaseEmbedderConfig( - deployment_name="text-embedding-ada-002", - http_async_client_proxies={"http://": "http://testproxy.mem0.net:8000"}, - ) - - _ = AzureOpenAIEmbedder(config=config) - - mock_embeddings.assert_called_once_with( - deployment="text-embedding-ada-002", - http_client=None, - http_async_client=mock_http_async_client_instance, - ) - mock_http_async_client.assert_called_once_with(proxies={"http://": "http://testproxy.mem0.net:8000"}) diff --git a/embedchain/tests/embedder/test_embedder.py b/embedchain/tests/embedder/test_embedder.py deleted file mode 100644 index 2797c2336..000000000 --- a/embedchain/tests/embedder/test_embedder.py +++ /dev/null @@ -1,49 +0,0 @@ -import pytest -from chromadb.api.types import Documents, Embeddings - -from embedchain.config.embedder.base import BaseEmbedderConfig -from embedchain.embedder.base import BaseEmbedder - - -@pytest.fixture -def base_embedder(): - return BaseEmbedder() - - -def test_initialization(base_embedder): - assert isinstance(base_embedder.config, BaseEmbedderConfig) - # not initialized - assert not hasattr(base_embedder, "embedding_fn") - assert not hasattr(base_embedder, "vector_dimension") - - -def test_set_embedding_fn(base_embedder): - def embedding_function(texts: Documents) -> Embeddings: - return [f"Embedding for {text}" for text in texts] - - base_embedder.set_embedding_fn(embedding_function) - assert hasattr(base_embedder, "embedding_fn") - assert callable(base_embedder.embedding_fn) - embeddings = base_embedder.embedding_fn(["text1", "text2"]) - assert embeddings == ["Embedding for text1", "Embedding for text2"] - - -def test_set_embedding_fn_when_not_a_function(base_embedder): - with pytest.raises(ValueError): - base_embedder.set_embedding_fn(None) - - -def test_set_vector_dimension(base_embedder): - base_embedder.set_vector_dimension(256) - assert hasattr(base_embedder, "vector_dimension") - assert base_embedder.vector_dimension == 256 - - -def test_set_vector_dimension_type_error(base_embedder): - with pytest.raises(TypeError): - base_embedder.set_vector_dimension(None) - - -def test_embedder_with_config(): - embedder = BaseEmbedder(BaseEmbedderConfig()) - assert isinstance(embedder.config, BaseEmbedderConfig) diff --git a/embedchain/tests/embedder/test_huggingface_embedder.py b/embedchain/tests/embedder/test_huggingface_embedder.py deleted file mode 100644 index ed97ccc91..000000000 --- a/embedchain/tests/embedder/test_huggingface_embedder.py +++ /dev/null @@ -1,19 +0,0 @@ - -from unittest.mock import patch - -from embedchain.config import BaseEmbedderConfig -from embedchain.embedder.huggingface import HuggingFaceEmbedder - - -def test_huggingface_embedder_with_model(monkeypatch): - config = BaseEmbedderConfig(model="test-model", model_kwargs={"param": "value"}) - with patch('embedchain.embedder.huggingface.HuggingFaceEmbeddings') as mock_embeddings: - embedder = HuggingFaceEmbedder(config=config) - assert embedder.config.model == "test-model" - assert embedder.config.model_kwargs == {"param": "value"} - mock_embeddings.assert_called_once_with( - model_name="test-model", - model_kwargs={"param": "value"} - ) - - diff --git a/embedchain/tests/evaluation/test_answer_relevancy_metric.py b/embedchain/tests/evaluation/test_answer_relevancy_metric.py deleted file mode 100644 index 03458ed38..000000000 --- a/embedchain/tests/evaluation/test_answer_relevancy_metric.py +++ /dev/null @@ -1,224 +0,0 @@ -import numpy as np -import pytest - -from embedchain.config.evaluation.base import AnswerRelevanceConfig -from embedchain.evaluation.metrics import AnswerRelevance -from embedchain.utils.evaluation import EvalData, EvalMetric - - -@pytest.fixture -def mock_data(): - return [ - EvalData( - contexts=[ - "This is a test context 1.", - ], - question="This is a test question 1.", - answer="This is a test answer 1.", - ), - EvalData( - contexts=[ - "This is a test context 2-1.", - "This is a test context 2-2.", - ], - question="This is a test question 2.", - answer="This is a test answer 2.", - ), - ] - - -@pytest.fixture -def mock_answer_relevance_metric(monkeypatch): - monkeypatch.setenv("OPENAI_API_KEY", "test_api_key") - monkeypatch.setenv("OPENAI_API_BASE", "test_api_base") - metric = AnswerRelevance() - return metric - - -def test_answer_relevance_init(monkeypatch): - monkeypatch.setenv("OPENAI_API_KEY", "test_api_key") - metric = AnswerRelevance() - assert metric.name == EvalMetric.ANSWER_RELEVANCY.value - assert metric.config.model == "gpt-4" - assert metric.config.embedder == "text-embedding-ada-002" - assert metric.config.api_key is None - assert metric.config.num_gen_questions == 1 - monkeypatch.delenv("OPENAI_API_KEY") - - -def test_answer_relevance_init_with_config(): - metric = AnswerRelevance(config=AnswerRelevanceConfig(api_key="test_api_key")) - assert metric.name == EvalMetric.ANSWER_RELEVANCY.value - assert metric.config.model == "gpt-4" - assert metric.config.embedder == "text-embedding-ada-002" - assert metric.config.api_key == "test_api_key" - assert metric.config.num_gen_questions == 1 - - -def test_answer_relevance_init_without_api_key(monkeypatch): - monkeypatch.delenv("OPENAI_API_KEY", raising=False) - with pytest.raises(ValueError): - AnswerRelevance() - - -def test_generate_prompt(mock_answer_relevance_metric, mock_data): - prompt = mock_answer_relevance_metric._generate_prompt(mock_data[0]) - assert "This is a test answer 1." in prompt - - prompt = mock_answer_relevance_metric._generate_prompt(mock_data[1]) - assert "This is a test answer 2." in prompt - - -def test_generate_questions(mock_answer_relevance_metric, mock_data, monkeypatch): - monkeypatch.setattr( - mock_answer_relevance_metric.client.chat.completions, - "create", - lambda model, messages: type( - "obj", - (object,), - { - "choices": [ - type( - "obj", - (object,), - {"message": type("obj", (object,), {"content": "This is a test question response.\n"})}, - ) - ] - }, - )(), - ) - prompt = mock_answer_relevance_metric._generate_prompt(mock_data[0]) - questions = mock_answer_relevance_metric._generate_questions(prompt) - assert len(questions) == 1 - - monkeypatch.setattr( - mock_answer_relevance_metric.client.chat.completions, - "create", - lambda model, messages: type( - "obj", - (object,), - { - "choices": [ - type("obj", (object,), {"message": type("obj", (object,), {"content": "question 1?\nquestion2?"})}) - ] - }, - )(), - ) - prompt = mock_answer_relevance_metric._generate_prompt(mock_data[1]) - questions = mock_answer_relevance_metric._generate_questions(prompt) - assert len(questions) == 2 - - -def test_generate_embedding(mock_answer_relevance_metric, mock_data, monkeypatch): - monkeypatch.setattr( - mock_answer_relevance_metric.client.embeddings, - "create", - lambda input, model: type("obj", (object,), {"data": [type("obj", (object,), {"embedding": [1, 2, 3]})]})(), - ) - embedding = mock_answer_relevance_metric._generate_embedding("This is a test question.") - assert len(embedding) == 3 - - -def test_compute_similarity(mock_answer_relevance_metric, mock_data): - original = np.array([1, 2, 3]) - generated = np.array([[1, 2, 3], [1, 2, 3]]) - similarity = mock_answer_relevance_metric._compute_similarity(original, generated) - assert len(similarity) == 2 - assert similarity[0] == 1.0 - assert similarity[1] == 1.0 - - -def test_compute_score(mock_answer_relevance_metric, mock_data, monkeypatch): - monkeypatch.setattr( - mock_answer_relevance_metric.client.chat.completions, - "create", - lambda model, messages: type( - "obj", - (object,), - { - "choices": [ - type( - "obj", - (object,), - {"message": type("obj", (object,), {"content": "This is a test question response.\n"})}, - ) - ] - }, - )(), - ) - monkeypatch.setattr( - mock_answer_relevance_metric.client.embeddings, - "create", - lambda input, model: type("obj", (object,), {"data": [type("obj", (object,), {"embedding": [1, 2, 3]})]})(), - ) - score = mock_answer_relevance_metric._compute_score(mock_data[0]) - assert score == 1.0 - - monkeypatch.setattr( - mock_answer_relevance_metric.client.chat.completions, - "create", - lambda model, messages: type( - "obj", - (object,), - { - "choices": [ - type("obj", (object,), {"message": type("obj", (object,), {"content": "question 1?\nquestion2?"})}) - ] - }, - )(), - ) - monkeypatch.setattr( - mock_answer_relevance_metric.client.embeddings, - "create", - lambda input, model: type("obj", (object,), {"data": [type("obj", (object,), {"embedding": [1, 2, 3]})]})(), - ) - score = mock_answer_relevance_metric._compute_score(mock_data[1]) - assert score == 1.0 - - -def test_evaluate(mock_answer_relevance_metric, mock_data, monkeypatch): - monkeypatch.setattr( - mock_answer_relevance_metric.client.chat.completions, - "create", - lambda model, messages: type( - "obj", - (object,), - { - "choices": [ - type( - "obj", - (object,), - {"message": type("obj", (object,), {"content": "This is a test question response.\n"})}, - ) - ] - }, - )(), - ) - monkeypatch.setattr( - mock_answer_relevance_metric.client.embeddings, - "create", - lambda input, model: type("obj", (object,), {"data": [type("obj", (object,), {"embedding": [1, 2, 3]})]})(), - ) - score = mock_answer_relevance_metric.evaluate(mock_data) - assert score == 1.0 - - monkeypatch.setattr( - mock_answer_relevance_metric.client.chat.completions, - "create", - lambda model, messages: type( - "obj", - (object,), - { - "choices": [ - type("obj", (object,), {"message": type("obj", (object,), {"content": "question 1?\nquestion2?"})}) - ] - }, - )(), - ) - monkeypatch.setattr( - mock_answer_relevance_metric.client.embeddings, - "create", - lambda input, model: type("obj", (object,), {"data": [type("obj", (object,), {"embedding": [1, 2, 3]})]})(), - ) - score = mock_answer_relevance_metric.evaluate(mock_data) - assert score == 1.0 diff --git a/embedchain/tests/evaluation/test_context_relevancy_metric.py b/embedchain/tests/evaluation/test_context_relevancy_metric.py deleted file mode 100644 index 6b4e13b10..000000000 --- a/embedchain/tests/evaluation/test_context_relevancy_metric.py +++ /dev/null @@ -1,100 +0,0 @@ -import pytest - -from embedchain.config.evaluation.base import ContextRelevanceConfig -from embedchain.evaluation.metrics import ContextRelevance -from embedchain.utils.evaluation import EvalData, EvalMetric - - -@pytest.fixture -def mock_data(): - return [ - EvalData( - contexts=[ - "This is a test context 1.", - ], - question="This is a test question 1.", - answer="This is a test answer 1.", - ), - EvalData( - contexts=[ - "This is a test context 2-1.", - "This is a test context 2-2.", - ], - question="This is a test question 2.", - answer="This is a test answer 2.", - ), - ] - - -@pytest.fixture -def mock_context_relevance_metric(monkeypatch): - monkeypatch.setenv("OPENAI_API_KEY", "test_api_key") - metric = ContextRelevance() - return metric - - -def test_context_relevance_init(monkeypatch): - monkeypatch.setenv("OPENAI_API_KEY", "test_api_key") - metric = ContextRelevance() - assert metric.name == EvalMetric.CONTEXT_RELEVANCY.value - assert metric.config.model == "gpt-4" - assert metric.config.api_key is None - assert metric.config.language == "en" - monkeypatch.delenv("OPENAI_API_KEY") - - -def test_context_relevance_init_with_config(): - metric = ContextRelevance(config=ContextRelevanceConfig(api_key="test_api_key")) - assert metric.name == EvalMetric.CONTEXT_RELEVANCY.value - assert metric.config.model == "gpt-4" - assert metric.config.api_key == "test_api_key" - assert metric.config.language == "en" - - -def test_context_relevance_init_without_api_key(monkeypatch): - monkeypatch.delenv("OPENAI_API_KEY", raising=False) - with pytest.raises(ValueError): - ContextRelevance() - - -def test_sentence_segmenter(mock_context_relevance_metric): - text = "This is a test sentence. This is another sentence." - assert mock_context_relevance_metric._sentence_segmenter(text) == [ - "This is a test sentence. ", - "This is another sentence.", - ] - - -def test_compute_score(mock_context_relevance_metric, mock_data, monkeypatch): - monkeypatch.setattr( - mock_context_relevance_metric.client.chat.completions, - "create", - lambda model, messages: type( - "obj", - (object,), - { - "choices": [ - type("obj", (object,), {"message": type("obj", (object,), {"content": "This is a test reponse."})}) - ] - }, - )(), - ) - assert mock_context_relevance_metric._compute_score(mock_data[0]) == 1.0 - assert mock_context_relevance_metric._compute_score(mock_data[1]) == 0.5 - - -def test_evaluate(mock_context_relevance_metric, mock_data, monkeypatch): - monkeypatch.setattr( - mock_context_relevance_metric.client.chat.completions, - "create", - lambda model, messages: type( - "obj", - (object,), - { - "choices": [ - type("obj", (object,), {"message": type("obj", (object,), {"content": "This is a test reponse."})}) - ] - }, - )(), - ) - assert mock_context_relevance_metric.evaluate(mock_data) == 0.75 diff --git a/embedchain/tests/evaluation/test_groundedness_metric.py b/embedchain/tests/evaluation/test_groundedness_metric.py deleted file mode 100644 index 38c3fec8e..000000000 --- a/embedchain/tests/evaluation/test_groundedness_metric.py +++ /dev/null @@ -1,152 +0,0 @@ -import numpy as np -import pytest - -from embedchain.config.evaluation.base import GroundednessConfig -from embedchain.evaluation.metrics import Groundedness -from embedchain.utils.evaluation import EvalData, EvalMetric - - -@pytest.fixture -def mock_data(): - return [ - EvalData( - contexts=[ - "This is a test context 1.", - ], - question="This is a test question 1.", - answer="This is a test answer 1.", - ), - EvalData( - contexts=[ - "This is a test context 2-1.", - "This is a test context 2-2.", - ], - question="This is a test question 2.", - answer="This is a test answer 2.", - ), - ] - - -@pytest.fixture -def mock_groundedness_metric(monkeypatch): - monkeypatch.setenv("OPENAI_API_KEY", "test_api_key") - metric = Groundedness() - return metric - - -def test_groundedness_init(monkeypatch): - monkeypatch.setenv("OPENAI_API_KEY", "test_api_key") - metric = Groundedness() - assert metric.name == EvalMetric.GROUNDEDNESS.value - assert metric.config.model == "gpt-4" - assert metric.config.api_key is None - monkeypatch.delenv("OPENAI_API_KEY") - - -def test_groundedness_init_with_config(): - metric = Groundedness(config=GroundednessConfig(api_key="test_api_key")) - assert metric.name == EvalMetric.GROUNDEDNESS.value - assert metric.config.model == "gpt-4" - assert metric.config.api_key == "test_api_key" - - -def test_groundedness_init_without_api_key(monkeypatch): - monkeypatch.delenv("OPENAI_API_KEY", raising=False) - with pytest.raises(ValueError): - Groundedness() - - -def test_generate_answer_claim_prompt(mock_groundedness_metric, mock_data): - prompt = mock_groundedness_metric._generate_answer_claim_prompt(data=mock_data[0]) - assert "This is a test question 1." in prompt - assert "This is a test answer 1." in prompt - - -def test_get_claim_statements(mock_groundedness_metric, mock_data, monkeypatch): - monkeypatch.setattr( - mock_groundedness_metric.client.chat.completions, - "create", - lambda *args, **kwargs: type( - "obj", - (object,), - { - "choices": [ - type( - "obj", - (object,), - { - "message": type( - "obj", - (object,), - { - "content": """This is a test answer 1. - This is a test answer 2. - This is a test answer 3.""" - }, - ) - }, - ) - ] - }, - )(), - ) - prompt = mock_groundedness_metric._generate_answer_claim_prompt(data=mock_data[0]) - claim_statements = mock_groundedness_metric._get_claim_statements(prompt=prompt) - assert len(claim_statements) == 3 - assert "This is a test answer 1." in claim_statements - - -def test_generate_claim_inference_prompt(mock_groundedness_metric, mock_data): - prompt = mock_groundedness_metric._generate_answer_claim_prompt(data=mock_data[0]) - claim_statements = [ - "This is a test claim 1.", - "This is a test claim 2.", - ] - prompt = mock_groundedness_metric._generate_claim_inference_prompt( - data=mock_data[0], claim_statements=claim_statements - ) - assert "This is a test context 1." in prompt - assert "This is a test claim 1." in prompt - - -def test_get_claim_verdict_scores(mock_groundedness_metric, mock_data, monkeypatch): - monkeypatch.setattr( - mock_groundedness_metric.client.chat.completions, - "create", - lambda *args, **kwargs: type( - "obj", - (object,), - {"choices": [type("obj", (object,), {"message": type("obj", (object,), {"content": "1\n0\n-1"})})]}, - )(), - ) - prompt = mock_groundedness_metric._generate_answer_claim_prompt(data=mock_data[0]) - claim_statements = mock_groundedness_metric._get_claim_statements(prompt=prompt) - prompt = mock_groundedness_metric._generate_claim_inference_prompt( - data=mock_data[0], claim_statements=claim_statements - ) - claim_verdict_scores = mock_groundedness_metric._get_claim_verdict_scores(prompt=prompt) - assert len(claim_verdict_scores) == 3 - assert claim_verdict_scores[0] == 1 - assert claim_verdict_scores[1] == 0 - - -def test_compute_score(mock_groundedness_metric, mock_data, monkeypatch): - monkeypatch.setattr( - mock_groundedness_metric, - "_get_claim_statements", - lambda *args, **kwargs: np.array( - [ - "This is a test claim 1.", - "This is a test claim 2.", - ] - ), - ) - monkeypatch.setattr(mock_groundedness_metric, "_get_claim_verdict_scores", lambda *args, **kwargs: np.array([1, 0])) - score = mock_groundedness_metric._compute_score(data=mock_data[0]) - assert score == 0.5 - - -def test_evaluate(mock_groundedness_metric, mock_data, monkeypatch): - monkeypatch.setattr(mock_groundedness_metric, "_compute_score", lambda *args, **kwargs: 0.5) - score = mock_groundedness_metric.evaluate(dataset=mock_data) - assert score == 0.5 diff --git a/embedchain/tests/helper_classes/test_json_serializable.py b/embedchain/tests/helper_classes/test_json_serializable.py deleted file mode 100644 index e68e05075..000000000 --- a/embedchain/tests/helper_classes/test_json_serializable.py +++ /dev/null @@ -1,81 +0,0 @@ -import random -import unittest -from string import Template - -from embedchain import App -from embedchain.config import AppConfig, BaseLlmConfig -from embedchain.helpers.json_serializable import ( - JSONSerializable, - register_deserializable, -) - - -class TestJsonSerializable(unittest.TestCase): - """Test that the datatype detection is working, based on the input.""" - - def test_base_function(self): - """Test that the base premise of serialization and deserealization is working""" - - @register_deserializable - class TestClass(JSONSerializable): - def __init__(self): - self.rng = random.random() - - original_class = TestClass() - serial = original_class.serialize() - - # Negative test to show that a new class does not have the same random number. - negative_test_class = TestClass() - self.assertNotEqual(original_class.rng, negative_test_class.rng) - - # Test to show that a deserialized class has the same random number. - positive_test_class: TestClass = TestClass().deserialize(serial) - self.assertEqual(original_class.rng, positive_test_class.rng) - self.assertTrue(isinstance(positive_test_class, TestClass)) - - # Test that it works as a static method too. - positive_test_class: TestClass = TestClass.deserialize(serial) - self.assertEqual(original_class.rng, positive_test_class.rng) - - # TODO: There's no reason it shouldn't work, but serialization to and from file should be tested too. - - def test_registration_required(self): - """Test that registration is required, and that without registration the default class is returned.""" - - class SecondTestClass(JSONSerializable): - def __init__(self): - self.default = True - - app = SecondTestClass() - # Make not default - app.default = False - # Serialize - serial = app.serialize() - # Deserialize. Due to the way errors are handled, it will not fail but return a default class. - app: SecondTestClass = SecondTestClass().deserialize(serial) - self.assertTrue(app.default) - # If we register and try again with the same serial, it should work - SecondTestClass._register_class_as_deserializable(SecondTestClass) - app: SecondTestClass = SecondTestClass().deserialize(serial) - self.assertFalse(app.default) - - def test_recursive(self): - """Test recursiveness with the real app""" - random_id = str(random.random()) - config = AppConfig(id=random_id, collect_metrics=False) - # config class is set under app.config. - app = App(config=config) - s = app.serialize() - new_app: App = App.deserialize(s) - # The id of the new app is the same as the first one. - self.assertEqual(random_id, new_app.config.id) - # We have proven that a nested class (app.config) can be serialized and deserialized just the same. - # TODO: test deeper recursion - - def test_special_subclasses(self): - """Test special subclasses that are not serializable by default.""" - # Template - config = BaseLlmConfig(template=Template("My custom template with $query, $context and $history.")) - s = config.serialize() - new_config: BaseLlmConfig = BaseLlmConfig.deserialize(s) - self.assertEqual(config.prompt.template, new_config.prompt.template) diff --git a/embedchain/tests/llm/conftest.py b/embedchain/tests/llm/conftest.py deleted file mode 100644 index 6e3da3d5d..000000000 --- a/embedchain/tests/llm/conftest.py +++ /dev/null @@ -1,10 +0,0 @@ - -from unittest import mock - -import pytest - - -@pytest.fixture(autouse=True) -def mock_alembic_command_upgrade(): - with mock.patch("alembic.command.upgrade"): - yield diff --git a/embedchain/tests/llm/test_anthrophic.py b/embedchain/tests/llm/test_anthrophic.py deleted file mode 100644 index fbf58d04d..000000000 --- a/embedchain/tests/llm/test_anthrophic.py +++ /dev/null @@ -1,54 +0,0 @@ -import os -from unittest.mock import patch - -import pytest -from langchain.schema import HumanMessage, SystemMessage - -from embedchain.config import BaseLlmConfig -from embedchain.llm.anthropic import AnthropicLlm - - -@pytest.fixture -def anthropic_llm(): - os.environ["ANTHROPIC_API_KEY"] = "test_api_key" - config = BaseLlmConfig(temperature=0.5, model="claude-instant-1", token_usage=False) - return AnthropicLlm(config) - - -def test_get_llm_model_answer(anthropic_llm): - with patch.object(AnthropicLlm, "_get_answer", return_value="Test Response") as mock_method: - prompt = "Test Prompt" - response = anthropic_llm.get_llm_model_answer(prompt) - assert response == "Test Response" - mock_method.assert_called_once_with(prompt, anthropic_llm.config) - - -def test_get_messages(anthropic_llm): - prompt = "Test Prompt" - system_prompt = "Test System Prompt" - messages = anthropic_llm._get_messages(prompt, system_prompt) - assert messages == [ - SystemMessage(content="Test System Prompt", additional_kwargs={}), - HumanMessage(content="Test Prompt", additional_kwargs={}, example=False), - ] - - -def test_get_llm_model_answer_with_token_usage(anthropic_llm): - test_config = BaseLlmConfig( - temperature=anthropic_llm.config.temperature, model=anthropic_llm.config.model, token_usage=True - ) - anthropic_llm.config = test_config - with patch.object( - AnthropicLlm, "_get_answer", return_value=("Test Response", {"input_tokens": 1, "output_tokens": 2}) - ) as mock_method: - prompt = "Test Prompt" - response, token_info = anthropic_llm.get_llm_model_answer(prompt) - assert response == "Test Response" - assert token_info == { - "prompt_tokens": 1, - "completion_tokens": 2, - "total_tokens": 3, - "total_cost": 1.265e-05, - "cost_currency": "USD", - } - mock_method.assert_called_once_with(prompt, anthropic_llm.config) diff --git a/embedchain/tests/llm/test_aws_bedrock.py b/embedchain/tests/llm/test_aws_bedrock.py deleted file mode 100644 index 440d8df3f..000000000 --- a/embedchain/tests/llm/test_aws_bedrock.py +++ /dev/null @@ -1,54 +0,0 @@ -import pytest -from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler - -from embedchain.config import BaseLlmConfig -from embedchain.llm.aws_bedrock import AWSBedrockLlm - - -@pytest.fixture -def config(monkeypatch): - monkeypatch.setenv("AWS_ACCESS_KEY_ID", "test_access_key_id") - monkeypatch.setenv("AWS_SECRET_ACCESS_KEY", "test_secret_access_key") - config = BaseLlmConfig( - model="amazon.titan-text-express-v1", - model_kwargs={ - "temperature": 0.5, - "topP": 1, - "maxTokenCount": 1000, - }, - ) - yield config - monkeypatch.delenv("AWS_ACCESS_KEY_ID") - monkeypatch.delenv("AWS_SECRET_ACCESS_KEY") - - -def test_get_llm_model_answer(config, mocker): - mocked_get_answer = mocker.patch("embedchain.llm.aws_bedrock.AWSBedrockLlm._get_answer", return_value="Test answer") - - llm = AWSBedrockLlm(config) - answer = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" - mocked_get_answer.assert_called_once_with("Test query", config) - - -def test_get_llm_model_answer_empty_prompt(config, mocker): - mocked_get_answer = mocker.patch("embedchain.llm.aws_bedrock.AWSBedrockLlm._get_answer", return_value="Test answer") - - llm = AWSBedrockLlm(config) - answer = llm.get_llm_model_answer("") - - assert answer == "Test answer" - mocked_get_answer.assert_called_once_with("", config) - - -def test_get_llm_model_answer_with_streaming(config, mocker): - config.stream = True - mocked_bedrock_chat = mocker.patch("embedchain.llm.aws_bedrock.BedrockLLM") - - llm = AWSBedrockLlm(config) - llm.get_llm_model_answer("Test query") - - mocked_bedrock_chat.assert_called_once() - callbacks = [callback[1]["callbacks"] for callback in mocked_bedrock_chat.call_args_list] - assert any(isinstance(callback[0], StreamingStdOutCallbackHandler) for callback in callbacks) diff --git a/embedchain/tests/llm/test_azure_openai.py b/embedchain/tests/llm/test_azure_openai.py deleted file mode 100644 index 605b8f389..000000000 --- a/embedchain/tests/llm/test_azure_openai.py +++ /dev/null @@ -1,164 +0,0 @@ -from unittest.mock import MagicMock, Mock, patch - -import httpx -import pytest -from langchain.schema import HumanMessage, SystemMessage - -from embedchain.config import BaseLlmConfig -from embedchain.llm.azure_openai import AzureOpenAILlm - - -@pytest.fixture -def azure_openai_llm(): - config = BaseLlmConfig( - deployment_name="azure_deployment", - temperature=0.7, - model="gpt-4o-mini", - max_tokens=50, - system_prompt="System Prompt", - ) - return AzureOpenAILlm(config) - - -def test_get_llm_model_answer(azure_openai_llm): - with patch.object(AzureOpenAILlm, "_get_answer", return_value="Test Response") as mock_method: - prompt = "Test Prompt" - response = azure_openai_llm.get_llm_model_answer(prompt) - assert response == "Test Response" - mock_method.assert_called_once_with(prompt=prompt, config=azure_openai_llm.config) - - -def test_get_answer(azure_openai_llm): - with patch("langchain_openai.AzureChatOpenAI") as mock_chat: - mock_chat_instance = mock_chat.return_value - mock_chat_instance.invoke.return_value = MagicMock(content="Test Response") - - prompt = "Test Prompt" - response = azure_openai_llm._get_answer(prompt, azure_openai_llm.config) - - assert response == "Test Response" - mock_chat.assert_called_once_with( - deployment_name=azure_openai_llm.config.deployment_name, - openai_api_version="2024-02-01", - model_name=azure_openai_llm.config.model or "gpt-4o-mini", - temperature=azure_openai_llm.config.temperature, - max_tokens=azure_openai_llm.config.max_tokens, - streaming=azure_openai_llm.config.stream, - http_client=None, - http_async_client=None, - ) - - -def test_get_messages(azure_openai_llm): - prompt = "Test Prompt" - system_prompt = "Test System Prompt" - messages = azure_openai_llm._get_messages(prompt, system_prompt) - assert messages == [ - SystemMessage(content="Test System Prompt", additional_kwargs={}), - HumanMessage(content="Test Prompt", additional_kwargs={}, example=False), - ] - - -def test_when_no_deployment_name_provided(): - config = BaseLlmConfig(temperature=0.7, model="gpt-4o-mini", max_tokens=50, system_prompt="System Prompt") - with pytest.raises(ValueError): - llm = AzureOpenAILlm(config) - llm.get_llm_model_answer("Test Prompt") - - -def test_with_api_version(): - config = BaseLlmConfig( - deployment_name="azure_deployment", - temperature=0.7, - model="gpt-4o-mini", - max_tokens=50, - system_prompt="System Prompt", - api_version="2024-02-01", - ) - - with patch("langchain_openai.AzureChatOpenAI") as mock_chat: - llm = AzureOpenAILlm(config) - llm.get_llm_model_answer("Test Prompt") - - mock_chat.assert_called_once_with( - deployment_name="azure_deployment", - openai_api_version="2024-02-01", - model_name="gpt-4o-mini", - temperature=0.7, - max_tokens=50, - streaming=False, - http_client=None, - http_async_client=None, - ) - - -def test_get_llm_model_answer_with_http_client_proxies(): - mock_http_client = Mock(spec=httpx.Client) - mock_http_client_instance = Mock(spec=httpx.Client) - mock_http_client.return_value = mock_http_client_instance - - with patch("langchain_openai.AzureChatOpenAI") as mock_chat, patch( - "httpx.Client", new=mock_http_client - ) as mock_http_client: - mock_chat.return_value.invoke.return_value.content = "Mocked response" - - config = BaseLlmConfig( - deployment_name="azure_deployment", - temperature=0.7, - max_tokens=50, - stream=False, - system_prompt="System prompt", - model="gpt-4o-mini", - http_client_proxies="http://testproxy.mem0.net:8000", - ) - - llm = AzureOpenAILlm(config) - llm.get_llm_model_answer("Test query") - - mock_chat.assert_called_once_with( - deployment_name="azure_deployment", - openai_api_version="2024-02-01", - model_name="gpt-4o-mini", - temperature=0.7, - max_tokens=50, - streaming=False, - http_client=mock_http_client_instance, - http_async_client=None, - ) - mock_http_client.assert_called_once_with(proxies="http://testproxy.mem0.net:8000") - - -def test_get_llm_model_answer_with_http_async_client_proxies(): - mock_http_async_client = Mock(spec=httpx.AsyncClient) - mock_http_async_client_instance = Mock(spec=httpx.AsyncClient) - mock_http_async_client.return_value = mock_http_async_client_instance - - with patch("langchain_openai.AzureChatOpenAI") as mock_chat, patch( - "httpx.AsyncClient", new=mock_http_async_client - ) as mock_http_async_client: - mock_chat.return_value.invoke.return_value.content = "Mocked response" - - config = BaseLlmConfig( - deployment_name="azure_deployment", - temperature=0.7, - max_tokens=50, - stream=False, - system_prompt="System prompt", - model="gpt-4o-mini", - http_async_client_proxies={"http://": "http://testproxy.mem0.net:8000"}, - ) - - llm = AzureOpenAILlm(config) - llm.get_llm_model_answer("Test query") - - mock_chat.assert_called_once_with( - deployment_name="azure_deployment", - openai_api_version="2024-02-01", - model_name="gpt-4o-mini", - temperature=0.7, - max_tokens=50, - streaming=False, - http_client=None, - http_async_client=mock_http_async_client_instance, - ) - mock_http_async_client.assert_called_once_with(proxies={"http://": "http://testproxy.mem0.net:8000"}) diff --git a/embedchain/tests/llm/test_base_llm.py b/embedchain/tests/llm/test_base_llm.py deleted file mode 100644 index 61e0ee01a..000000000 --- a/embedchain/tests/llm/test_base_llm.py +++ /dev/null @@ -1,61 +0,0 @@ -from string import Template - -import pytest - -from embedchain.llm.base import BaseLlm, BaseLlmConfig - - -@pytest.fixture -def base_llm(): - config = BaseLlmConfig() - return BaseLlm(config=config) - - -def test_is_get_llm_model_answer_not_implemented(base_llm): - with pytest.raises(NotImplementedError): - base_llm.get_llm_model_answer() - - -def test_is_stream_bool(): - with pytest.raises(ValueError): - config = BaseLlmConfig(stream="test value") - BaseLlm(config=config) - - -def test_template_string_gets_converted_to_Template_instance(): - config = BaseLlmConfig(template="test value $query $context") - llm = BaseLlm(config=config) - assert isinstance(llm.config.prompt, Template) - - -def test_is_get_llm_model_answer_implemented(): - class TestLlm(BaseLlm): - def get_llm_model_answer(self): - return "Implemented" - - config = BaseLlmConfig() - llm = TestLlm(config=config) - assert llm.get_llm_model_answer() == "Implemented" - - -def test_stream_response(base_llm): - answer = ["Chunk1", "Chunk2", "Chunk3"] - result = list(base_llm._stream_response(answer)) - assert result == answer - - -def test_append_search_and_context(base_llm): - context = "Context" - web_search_result = "Web Search Result" - result = base_llm._append_search_and_context(context, web_search_result) - expected_result = "Context\nWeb Search Result: Web Search Result" - assert result == expected_result - - -def test_access_search_and_get_results(base_llm, mocker): - base_llm.access_search_and_get_results = mocker.patch.object( - base_llm, "access_search_and_get_results", return_value="Search Results" - ) - input_query = "Test query" - result = base_llm.access_search_and_get_results(input_query) - assert result == "Search Results" diff --git a/embedchain/tests/llm/test_chat.py b/embedchain/tests/llm/test_chat.py deleted file mode 100644 index 991a0adf0..000000000 --- a/embedchain/tests/llm/test_chat.py +++ /dev/null @@ -1,120 +0,0 @@ -import os -import unittest -from unittest.mock import MagicMock, patch - -from embedchain import App -from embedchain.config import AppConfig, BaseLlmConfig -from embedchain.llm.base import BaseLlm -from embedchain.memory.base import ChatHistory -from embedchain.memory.message import ChatMessage - - -class TestApp(unittest.TestCase): - def setUp(self): - os.environ["OPENAI_API_KEY"] = "test_key" - self.app = App(config=AppConfig(collect_metrics=False)) - - @patch.object(App, "_retrieve_from_database", return_value=["Test context"]) - @patch.object(BaseLlm, "get_answer_from_llm", return_value="Test answer") - def test_chat_with_memory(self, mock_get_answer, mock_retrieve): - """ - This test checks the functionality of the 'chat' method in the App class with respect to the chat history - memory. - The 'chat' method is called twice. The first call initializes the chat history memory. - The second call is expected to use the chat history from the first call. - - Key assumptions tested: - called with correct arguments, adding the correct chat history. - - After the first call, 'memory.chat_memory.add_user_message' and 'memory.chat_memory.add_ai_message' are - - During the second call, the 'chat' method uses the chat history from the first call. - - The test isolates the 'chat' method behavior by mocking out '_retrieve_from_database', 'get_answer_from_llm' and - 'memory' methods. - """ - config = AppConfig(collect_metrics=False) - app = App(config=config) - with patch.object(BaseLlm, "add_history") as mock_history: - first_answer = app.chat("Test query 1") - self.assertEqual(first_answer, "Test answer") - mock_history.assert_called_with(app.config.id, "Test query 1", "Test answer", session_id="default") - - second_answer = app.chat("Test query 2", session_id="test_session") - self.assertEqual(second_answer, "Test answer") - mock_history.assert_called_with(app.config.id, "Test query 2", "Test answer", session_id="test_session") - - @patch.object(App, "_retrieve_from_database", return_value=["Test context"]) - @patch.object(BaseLlm, "get_answer_from_llm", return_value="Test answer") - def test_template_replacement(self, mock_get_answer, mock_retrieve): - """ - Tests that if a default template is used and it doesn't contain history, - the default template is swapped in. - - Also tests that a dry run does not change the history - """ - with patch.object(ChatHistory, "get") as mock_memory: - mock_message = ChatMessage() - mock_message.add_user_message("Test query 1") - mock_message.add_ai_message("Test answer") - mock_memory.return_value = [mock_message] - - config = AppConfig(collect_metrics=False) - app = App(config=config) - first_answer = app.chat("Test query 1") - self.assertEqual(first_answer, "Test answer") - self.assertEqual(len(app.llm.history), 1) - history = app.llm.history - dry_run = app.chat("Test query 2", dry_run=True) - self.assertIn("Conversation history:", dry_run) - self.assertEqual(history, app.llm.history) - self.assertEqual(len(app.llm.history), 1) - - @patch("chromadb.api.models.Collection.Collection.add", MagicMock) - def test_chat_with_where_in_params(self): - """ - Test where filter - """ - with patch.object(self.app, "_retrieve_from_database") as mock_retrieve: - mock_retrieve.return_value = ["Test context"] - with patch.object(self.app.llm, "get_llm_model_answer") as mock_answer: - mock_answer.return_value = "Test answer" - answer = self.app.chat("Test query", where={"attribute": "value"}) - - self.assertEqual(answer, "Test answer") - _args, kwargs = mock_retrieve.call_args - self.assertEqual(kwargs.get("input_query"), "Test query") - self.assertEqual(kwargs.get("where"), {"attribute": "value"}) - mock_answer.assert_called_once() - - @patch("chromadb.api.models.Collection.Collection.add", MagicMock) - def test_chat_with_where_in_chat_config(self): - """ - This test checks the functionality of the 'chat' method in the App class. - It simulates a scenario where the '_retrieve_from_database' method returns a context list based on - a where filter and 'get_llm_model_answer' returns an expected answer string. - - The 'chat' method is expected to call '_retrieve_from_database' with the where filter specified - in the BaseLlmConfig and 'get_llm_model_answer' methods appropriately and return the right answer. - - Key assumptions tested: - - '_retrieve_from_database' method is called exactly once with arguments: "Test query" and an instance of - BaseLlmConfig. - - 'get_llm_model_answer' is called exactly once. The specific arguments are not checked in this test. - - 'chat' method returns the value it received from 'get_llm_model_answer'. - - The test isolates the 'chat' method behavior by mocking out '_retrieve_from_database' and - 'get_llm_model_answer' methods. - """ - with patch.object(self.app.llm, "get_llm_model_answer") as mock_answer: - mock_answer.return_value = "Test answer" - with patch.object(self.app.db, "query") as mock_database_query: - mock_database_query.return_value = ["Test context"] - llm_config = BaseLlmConfig(where={"attribute": "value"}) - answer = self.app.chat("Test query", llm_config) - - self.assertEqual(answer, "Test answer") - _args, kwargs = mock_database_query.call_args - self.assertEqual(kwargs.get("input_query"), "Test query") - where = kwargs.get("where") - assert "app_id" in where - assert "attribute" in where - mock_answer.assert_called_once() diff --git a/embedchain/tests/llm/test_clarifai.py b/embedchain/tests/llm/test_clarifai.py deleted file mode 100644 index 884fe63da..000000000 --- a/embedchain/tests/llm/test_clarifai.py +++ /dev/null @@ -1,23 +0,0 @@ - -import pytest - -from embedchain.config import BaseLlmConfig -from embedchain.llm.clarifai import ClarifaiLlm - - -@pytest.fixture -def clarifai_llm_config(monkeypatch): - monkeypatch.setenv("CLARIFAI_PAT","test_api_key") - config = BaseLlmConfig( - model="https://clarifai.com/openai/chat-completion/models/GPT-4", - model_kwargs={"temperature": 0.7, "max_tokens": 100}, - ) - yield config - monkeypatch.delenv("CLARIFAI_PAT") - -def test_clarifai__llm_get_llm_model_answer(clarifai_llm_config, mocker): - mocker.patch("embedchain.llm.clarifai.ClarifaiLlm._get_answer", return_value="Test answer") - llm = ClarifaiLlm(clarifai_llm_config) - answer = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" diff --git a/embedchain/tests/llm/test_cohere.py b/embedchain/tests/llm/test_cohere.py deleted file mode 100644 index 20068f16c..000000000 --- a/embedchain/tests/llm/test_cohere.py +++ /dev/null @@ -1,73 +0,0 @@ -import os - -import pytest - -from embedchain.config import BaseLlmConfig -from embedchain.llm.cohere import CohereLlm - - -@pytest.fixture -def cohere_llm_config(): - os.environ["COHERE_API_KEY"] = "test_api_key" - config = BaseLlmConfig(model="command-r", max_tokens=100, temperature=0.7, top_p=0.8, token_usage=False) - yield config - os.environ.pop("COHERE_API_KEY") - - -def test_init_raises_value_error_without_api_key(mocker): - mocker.patch.dict(os.environ, clear=True) - with pytest.raises(ValueError): - CohereLlm() - - -def test_get_llm_model_answer_raises_value_error_for_system_prompt(cohere_llm_config): - llm = CohereLlm(cohere_llm_config) - llm.config.system_prompt = "system_prompt" - with pytest.raises(ValueError): - llm.get_llm_model_answer("prompt") - - -def test_get_llm_model_answer(cohere_llm_config, mocker): - mocker.patch("embedchain.llm.cohere.CohereLlm._get_answer", return_value="Test answer") - - llm = CohereLlm(cohere_llm_config) - answer = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" - - -def test_get_llm_model_answer_with_token_usage(cohere_llm_config, mocker): - test_config = BaseLlmConfig( - temperature=cohere_llm_config.temperature, - max_tokens=cohere_llm_config.max_tokens, - top_p=cohere_llm_config.top_p, - model=cohere_llm_config.model, - token_usage=True, - ) - mocker.patch( - "embedchain.llm.cohere.CohereLlm._get_answer", - return_value=("Test answer", {"input_tokens": 1, "output_tokens": 2}), - ) - - llm = CohereLlm(test_config) - answer, token_info = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" - assert token_info == { - "prompt_tokens": 1, - "completion_tokens": 2, - "total_tokens": 3, - "total_cost": 3.5e-06, - "cost_currency": "USD", - } - - -def test_get_answer_mocked_cohere(cohere_llm_config, mocker): - mocked_cohere = mocker.patch("embedchain.llm.cohere.ChatCohere") - mocked_cohere.return_value.invoke.return_value.content = "Mocked answer" - - llm = CohereLlm(cohere_llm_config) - prompt = "Test query" - answer = llm.get_llm_model_answer(prompt) - - assert answer == "Mocked answer" diff --git a/embedchain/tests/llm/test_generate_prompt.py b/embedchain/tests/llm/test_generate_prompt.py deleted file mode 100644 index e283c3f81..000000000 --- a/embedchain/tests/llm/test_generate_prompt.py +++ /dev/null @@ -1,70 +0,0 @@ -import unittest -from string import Template - -from embedchain import App -from embedchain.config import AppConfig, BaseLlmConfig - - -class TestGeneratePrompt(unittest.TestCase): - def setUp(self): - self.app = App(config=AppConfig(collect_metrics=False)) - - def test_generate_prompt_with_template(self): - """ - Tests that the generate_prompt method correctly formats the prompt using - a custom template provided in the BaseLlmConfig instance. - - This test sets up a scenario with an input query and a list of contexts, - and a custom template, and then calls generate_prompt. It checks that the - returned prompt correctly incorporates all the contexts and the query into - the format specified by the template. - """ - # Setup - input_query = "Test query" - contexts = ["Context 1", "Context 2", "Context 3"] - template = "You are a bot. Context: ${context} - Query: ${query} - Helpful answer:" - config = BaseLlmConfig(template=Template(template)) - self.app.llm.config = config - - # Execute - result = self.app.llm.generate_prompt(input_query, contexts) - - # Assert - expected_result = ( - "You are a bot. Context: Context 1 | Context 2 | Context 3 - Query: Test query - Helpful answer:" - ) - self.assertEqual(result, expected_result) - - def test_generate_prompt_with_contexts_list(self): - """ - Tests that the generate_prompt method correctly handles a list of contexts. - - This test sets up a scenario with an input query and a list of contexts, - and then calls generate_prompt. It checks that the returned prompt - correctly includes all the contexts and the query. - """ - # Setup - input_query = "Test query" - contexts = ["Context 1", "Context 2", "Context 3"] - config = BaseLlmConfig() - - # Execute - self.app.llm.config = config - result = self.app.llm.generate_prompt(input_query, contexts) - - # Assert - expected_result = config.prompt.substitute(context="Context 1 | Context 2 | Context 3", query=input_query) - self.assertEqual(result, expected_result) - - def test_generate_prompt_with_history(self): - """ - Test the 'generate_prompt' method with BaseLlmConfig containing a history attribute. - """ - config = BaseLlmConfig() - config.prompt = Template("Context: $context | Query: $query | History: $history") - self.app.llm.config = config - self.app.llm.set_history(["Past context 1", "Past context 2"]) - prompt = self.app.llm.generate_prompt("Test query", ["Test context"]) - - expected_prompt = "Context: Test context | Query: Test query | History: Past context 1\nPast context 2" - self.assertEqual(prompt, expected_prompt) diff --git a/embedchain/tests/llm/test_google.py b/embedchain/tests/llm/test_google.py deleted file mode 100644 index d2ba301e6..000000000 --- a/embedchain/tests/llm/test_google.py +++ /dev/null @@ -1,43 +0,0 @@ -import pytest - -from embedchain.config import BaseLlmConfig -from embedchain.llm.google import GoogleLlm - - -@pytest.fixture -def google_llm_config(): - return BaseLlmConfig(model="gemini-pro", max_tokens=100, temperature=0.7, top_p=0.5, stream=False) - - -def test_google_llm_init_missing_api_key(monkeypatch): - monkeypatch.delenv("GOOGLE_API_KEY", raising=False) - with pytest.raises(ValueError, match="Please set the GOOGLE_API_KEY environment variable."): - GoogleLlm() - - -def test_google_llm_init(monkeypatch): - monkeypatch.setenv("GOOGLE_API_KEY", "fake_api_key") - with monkeypatch.context() as m: - m.setattr("importlib.import_module", lambda x: None) - google_llm = GoogleLlm() - assert google_llm is not None - - -def test_google_llm_get_llm_model_answer_with_system_prompt(monkeypatch): - monkeypatch.setenv("GOOGLE_API_KEY", "fake_api_key") - monkeypatch.setattr("importlib.import_module", lambda x: None) - google_llm = GoogleLlm(config=BaseLlmConfig(system_prompt="system prompt")) - with pytest.raises(ValueError, match="GoogleLlm does not support `system_prompt`"): - google_llm.get_llm_model_answer("test prompt") - - -def test_google_llm_get_llm_model_answer(monkeypatch, google_llm_config): - def mock_get_answer(prompt, config): - return "Generated Text" - - monkeypatch.setenv("GOOGLE_API_KEY", "fake_api_key") - monkeypatch.setattr(GoogleLlm, "_get_answer", mock_get_answer) - google_llm = GoogleLlm(config=google_llm_config) - result = google_llm.get_llm_model_answer("test prompt") - - assert result == "Generated Text" diff --git a/embedchain/tests/llm/test_gpt4all.py b/embedchain/tests/llm/test_gpt4all.py deleted file mode 100644 index a65f5aa5a..000000000 --- a/embedchain/tests/llm/test_gpt4all.py +++ /dev/null @@ -1,60 +0,0 @@ -import pytest -from langchain_community.llms.gpt4all import GPT4All as LangchainGPT4All - -from embedchain.config import BaseLlmConfig -from embedchain.llm.gpt4all import GPT4ALLLlm - - -@pytest.fixture -def config(): - config = BaseLlmConfig( - temperature=0.7, - max_tokens=50, - top_p=0.8, - stream=False, - system_prompt="System prompt", - model="orca-mini-3b-gguf2-q4_0.gguf", - ) - yield config - - -@pytest.fixture -def gpt4all_with_config(config): - return GPT4ALLLlm(config=config) - - -@pytest.fixture -def gpt4all_without_config(): - return GPT4ALLLlm() - - -def test_gpt4all_init_with_config(config, gpt4all_with_config): - assert gpt4all_with_config.config.temperature == config.temperature - assert gpt4all_with_config.config.max_tokens == config.max_tokens - assert gpt4all_with_config.config.top_p == config.top_p - assert gpt4all_with_config.config.stream == config.stream - assert gpt4all_with_config.config.system_prompt == config.system_prompt - assert gpt4all_with_config.config.model == config.model - - assert isinstance(gpt4all_with_config.instance, LangchainGPT4All) - - -def test_gpt4all_init_without_config(gpt4all_without_config): - assert gpt4all_without_config.config.model == "orca-mini-3b-gguf2-q4_0.gguf" - assert isinstance(gpt4all_without_config.instance, LangchainGPT4All) - - -def test_get_llm_model_answer(mocker, gpt4all_with_config): - test_query = "Test query" - test_answer = "Test answer" - - mocked_get_answer = mocker.patch("embedchain.llm.gpt4all.GPT4ALLLlm._get_answer", return_value=test_answer) - answer = gpt4all_with_config.get_llm_model_answer(test_query) - - assert answer == test_answer - mocked_get_answer.assert_called_once_with(prompt=test_query, config=gpt4all_with_config.config) - - -def test_gpt4all_model_switching(gpt4all_with_config): - with pytest.raises(RuntimeError, match="GPT4ALLLlm does not support switching models at runtime."): - gpt4all_with_config._get_answer("Test prompt", BaseLlmConfig(model="new_model")) diff --git a/embedchain/tests/llm/test_huggingface.py b/embedchain/tests/llm/test_huggingface.py deleted file mode 100644 index 754317f6b..000000000 --- a/embedchain/tests/llm/test_huggingface.py +++ /dev/null @@ -1,83 +0,0 @@ -import importlib -import os - -import pytest - -from embedchain.config import BaseLlmConfig -from embedchain.llm.huggingface import HuggingFaceLlm - - -@pytest.fixture -def huggingface_llm_config(): - os.environ["HUGGINGFACE_ACCESS_TOKEN"] = "test_access_token" - config = BaseLlmConfig(model="google/flan-t5-xxl", max_tokens=50, temperature=0.7, top_p=0.8) - yield config - os.environ.pop("HUGGINGFACE_ACCESS_TOKEN") - - -@pytest.fixture -def huggingface_endpoint_config(): - os.environ["HUGGINGFACE_ACCESS_TOKEN"] = "test_access_token" - config = BaseLlmConfig(endpoint="https://api-inference.huggingface.co/models/gpt2", model_kwargs={"device": "cpu"}) - yield config - os.environ.pop("HUGGINGFACE_ACCESS_TOKEN") - - -def test_init_raises_value_error_without_api_key(mocker): - mocker.patch.dict(os.environ, clear=True) - with pytest.raises(ValueError): - HuggingFaceLlm() - - -def test_get_llm_model_answer_raises_value_error_for_system_prompt(huggingface_llm_config): - llm = HuggingFaceLlm(huggingface_llm_config) - llm.config.system_prompt = "system_prompt" - with pytest.raises(ValueError): - llm.get_llm_model_answer("prompt") - - -def test_top_p_value_within_range(): - config = BaseLlmConfig(top_p=1.0) - with pytest.raises(ValueError): - HuggingFaceLlm._get_answer("test_prompt", config) - - -def test_dependency_is_imported(): - importlib_installed = True - try: - importlib.import_module("huggingface_hub") - except ImportError: - importlib_installed = False - assert importlib_installed - - -def test_get_llm_model_answer(huggingface_llm_config, mocker): - mocker.patch("embedchain.llm.huggingface.HuggingFaceLlm._get_answer", return_value="Test answer") - - llm = HuggingFaceLlm(huggingface_llm_config) - answer = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" - - -def test_hugging_face_mock(huggingface_llm_config, mocker): - mock_llm_instance = mocker.Mock(return_value="Test answer") - mock_hf_hub = mocker.patch("embedchain.llm.huggingface.HuggingFaceHub") - mock_hf_hub.return_value.invoke = mock_llm_instance - - llm = HuggingFaceLlm(huggingface_llm_config) - answer = llm.get_llm_model_answer("Test query") - assert answer == "Test answer" - mock_llm_instance.assert_called_once_with("Test query") - - -def test_custom_endpoint(huggingface_endpoint_config, mocker): - mock_llm_instance = mocker.Mock(return_value="Test answer") - mock_hf_endpoint = mocker.patch("embedchain.llm.huggingface.HuggingFaceEndpoint") - mock_hf_endpoint.return_value.invoke = mock_llm_instance - - llm = HuggingFaceLlm(huggingface_endpoint_config) - answer = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" - mock_llm_instance.assert_called_once_with("Test query") diff --git a/embedchain/tests/llm/test_jina.py b/embedchain/tests/llm/test_jina.py deleted file mode 100644 index 8df933222..000000000 --- a/embedchain/tests/llm/test_jina.py +++ /dev/null @@ -1,79 +0,0 @@ -import os - -import pytest -from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler - -from embedchain.config import BaseLlmConfig -from embedchain.llm.jina import JinaLlm - - -@pytest.fixture -def config(): - os.environ["JINACHAT_API_KEY"] = "test_api_key" - config = BaseLlmConfig(temperature=0.7, max_tokens=50, top_p=0.8, stream=False, system_prompt="System prompt") - yield config - os.environ.pop("JINACHAT_API_KEY") - - -def test_init_raises_value_error_without_api_key(mocker): - mocker.patch.dict(os.environ, clear=True) - with pytest.raises(ValueError): - JinaLlm() - - -def test_get_llm_model_answer(config, mocker): - mocked_get_answer = mocker.patch("embedchain.llm.jina.JinaLlm._get_answer", return_value="Test answer") - - llm = JinaLlm(config) - answer = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" - mocked_get_answer.assert_called_once_with("Test query", config) - - -def test_get_llm_model_answer_with_system_prompt(config, mocker): - config.system_prompt = "Custom system prompt" - mocked_get_answer = mocker.patch("embedchain.llm.jina.JinaLlm._get_answer", return_value="Test answer") - - llm = JinaLlm(config) - answer = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" - mocked_get_answer.assert_called_once_with("Test query", config) - - -def test_get_llm_model_answer_empty_prompt(config, mocker): - mocked_get_answer = mocker.patch("embedchain.llm.jina.JinaLlm._get_answer", return_value="Test answer") - - llm = JinaLlm(config) - answer = llm.get_llm_model_answer("") - - assert answer == "Test answer" - mocked_get_answer.assert_called_once_with("", config) - - -def test_get_llm_model_answer_with_streaming(config, mocker): - config.stream = True - mocked_jinachat = mocker.patch("embedchain.llm.jina.JinaChat") - - llm = JinaLlm(config) - llm.get_llm_model_answer("Test query") - - mocked_jinachat.assert_called_once() - callbacks = [callback[1]["callbacks"] for callback in mocked_jinachat.call_args_list] - assert any(isinstance(callback[0], StreamingStdOutCallbackHandler) for callback in callbacks) - - -def test_get_llm_model_answer_without_system_prompt(config, mocker): - config.system_prompt = None - mocked_jinachat = mocker.patch("embedchain.llm.jina.JinaChat") - - llm = JinaLlm(config) - llm.get_llm_model_answer("Test query") - - mocked_jinachat.assert_called_once_with( - temperature=config.temperature, - max_tokens=config.max_tokens, - jinachat_api_key=os.environ["JINACHAT_API_KEY"], - model_kwargs={"top_p": config.top_p}, - ) diff --git a/embedchain/tests/llm/test_llama2.py b/embedchain/tests/llm/test_llama2.py deleted file mode 100644 index a9dd4049e..000000000 --- a/embedchain/tests/llm/test_llama2.py +++ /dev/null @@ -1,40 +0,0 @@ -import os - -import pytest - -from embedchain.llm.llama2 import Llama2Llm - - -@pytest.fixture -def llama2_llm(): - os.environ["REPLICATE_API_TOKEN"] = "test_api_token" - llm = Llama2Llm() - return llm - - -def test_init_raises_value_error_without_api_key(mocker): - mocker.patch.dict(os.environ, clear=True) - with pytest.raises(ValueError): - Llama2Llm() - - -def test_get_llm_model_answer_raises_value_error_for_system_prompt(llama2_llm): - llama2_llm.config.system_prompt = "system_prompt" - with pytest.raises(ValueError): - llama2_llm.get_llm_model_answer("prompt") - - -def test_get_llm_model_answer(llama2_llm, mocker): - mocked_replicate = mocker.patch("embedchain.llm.llama2.Replicate") - mocked_replicate_instance = mocker.MagicMock() - mocked_replicate.return_value = mocked_replicate_instance - mocked_replicate_instance.invoke.return_value = "Test answer" - - llama2_llm.config.model = "test_model" - llama2_llm.config.max_tokens = 50 - llama2_llm.config.temperature = 0.7 - llama2_llm.config.top_p = 0.8 - - answer = llama2_llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" diff --git a/embedchain/tests/llm/test_mistralai.py b/embedchain/tests/llm/test_mistralai.py deleted file mode 100644 index 9fc5e0873..000000000 --- a/embedchain/tests/llm/test_mistralai.py +++ /dev/null @@ -1,87 +0,0 @@ -import pytest - -from embedchain.config import BaseLlmConfig -from embedchain.llm.mistralai import MistralAILlm - - -@pytest.fixture -def mistralai_llm_config(monkeypatch): - monkeypatch.setenv("MISTRAL_API_KEY", "fake_api_key") - yield BaseLlmConfig(model="mistral-tiny", max_tokens=100, temperature=0.7, top_p=0.5, stream=False) - monkeypatch.delenv("MISTRAL_API_KEY", raising=False) - - -def test_mistralai_llm_init_missing_api_key(monkeypatch): - monkeypatch.delenv("MISTRAL_API_KEY", raising=False) - with pytest.raises(ValueError, match="Please set the MISTRAL_API_KEY environment variable."): - MistralAILlm() - - -def test_mistralai_llm_init(monkeypatch): - monkeypatch.setenv("MISTRAL_API_KEY", "fake_api_key") - llm = MistralAILlm() - assert llm is not None - - -def test_get_llm_model_answer(monkeypatch, mistralai_llm_config): - def mock_get_answer(self, prompt, config): - return "Generated Text" - - monkeypatch.setattr(MistralAILlm, "_get_answer", mock_get_answer) - llm = MistralAILlm(config=mistralai_llm_config) - result = llm.get_llm_model_answer("test prompt") - - assert result == "Generated Text" - - -def test_get_llm_model_answer_with_system_prompt(monkeypatch, mistralai_llm_config): - mistralai_llm_config.system_prompt = "Test system prompt" - monkeypatch.setattr(MistralAILlm, "_get_answer", lambda self, prompt, config: "Generated Text") - llm = MistralAILlm(config=mistralai_llm_config) - result = llm.get_llm_model_answer("test prompt") - - assert result == "Generated Text" - - -def test_get_llm_model_answer_empty_prompt(monkeypatch, mistralai_llm_config): - monkeypatch.setattr(MistralAILlm, "_get_answer", lambda self, prompt, config: "Generated Text") - llm = MistralAILlm(config=mistralai_llm_config) - result = llm.get_llm_model_answer("") - - assert result == "Generated Text" - - -def test_get_llm_model_answer_without_system_prompt(monkeypatch, mistralai_llm_config): - mistralai_llm_config.system_prompt = None - monkeypatch.setattr(MistralAILlm, "_get_answer", lambda self, prompt, config: "Generated Text") - llm = MistralAILlm(config=mistralai_llm_config) - result = llm.get_llm_model_answer("test prompt") - - assert result == "Generated Text" - - -def test_get_llm_model_answer_with_token_usage(monkeypatch, mistralai_llm_config): - test_config = BaseLlmConfig( - temperature=mistralai_llm_config.temperature, - max_tokens=mistralai_llm_config.max_tokens, - top_p=mistralai_llm_config.top_p, - model=mistralai_llm_config.model, - token_usage=True, - ) - monkeypatch.setattr( - MistralAILlm, - "_get_answer", - lambda self, prompt, config: ("Generated Text", {"prompt_tokens": 1, "completion_tokens": 2}), - ) - - llm = MistralAILlm(test_config) - answer, token_info = llm.get_llm_model_answer("Test query") - - assert answer == "Generated Text" - assert token_info == { - "prompt_tokens": 1, - "completion_tokens": 2, - "total_tokens": 3, - "total_cost": 7.5e-07, - "cost_currency": "USD", - } diff --git a/embedchain/tests/llm/test_ollama.py b/embedchain/tests/llm/test_ollama.py deleted file mode 100644 index b0d932635..000000000 --- a/embedchain/tests/llm/test_ollama.py +++ /dev/null @@ -1,52 +0,0 @@ -import pytest -from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler - -from embedchain.config import BaseLlmConfig -from embedchain.llm.ollama import OllamaLlm - - -@pytest.fixture -def ollama_llm_config(): - config = BaseLlmConfig(model="llama2", temperature=0.7, top_p=0.8, stream=True, system_prompt=None) - yield config - - -def test_get_llm_model_answer(ollama_llm_config, mocker): - mocker.patch("embedchain.llm.ollama.Client.list", return_value={"models": [{"name": "llama2"}]}) - mocker.patch("embedchain.llm.ollama.OllamaLlm._get_answer", return_value="Test answer") - - llm = OllamaLlm(ollama_llm_config) - answer = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" - - -def test_get_answer_mocked_ollama(ollama_llm_config, mocker): - mocker.patch("embedchain.llm.ollama.Client.list", return_value={"models": [{"name": "llama2"}]}) - mocked_ollama = mocker.patch("embedchain.llm.ollama.Ollama") - mock_instance = mocked_ollama.return_value - mock_instance.invoke.return_value = "Mocked answer" - - llm = OllamaLlm(ollama_llm_config) - prompt = "Test query" - answer = llm.get_llm_model_answer(prompt) - - assert answer == "Mocked answer" - - -def test_get_llm_model_answer_with_streaming(ollama_llm_config, mocker): - ollama_llm_config.stream = True - ollama_llm_config.callbacks = [StreamingStdOutCallbackHandler()] - mocker.patch("embedchain.llm.ollama.Client.list", return_value={"models": [{"name": "llama2"}]}) - mocked_ollama_chat = mocker.patch("embedchain.llm.ollama.OllamaLlm._get_answer", return_value="Test answer") - - llm = OllamaLlm(ollama_llm_config) - llm.get_llm_model_answer("Test query") - - mocked_ollama_chat.assert_called_once() - call_args = mocked_ollama_chat.call_args - config_arg = call_args[1]["config"] - callbacks = config_arg.callbacks - - assert len(callbacks) == 1 - assert isinstance(callbacks[0], StreamingStdOutCallbackHandler) diff --git a/embedchain/tests/llm/test_openai.py b/embedchain/tests/llm/test_openai.py deleted file mode 100644 index 5cff056ac..000000000 --- a/embedchain/tests/llm/test_openai.py +++ /dev/null @@ -1,267 +0,0 @@ -import os - -import httpx -import pytest -from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler - -from embedchain.config import BaseLlmConfig -from embedchain.llm.openai import OpenAILlm - - -@pytest.fixture() -def env_config(): - os.environ["OPENAI_API_KEY"] = "test_api_key" - os.environ["OPENAI_API_BASE"] = "https://api.openai.com/v1/engines/" - yield - os.environ.pop("OPENAI_API_KEY") - - -@pytest.fixture -def config(env_config): - config = BaseLlmConfig( - temperature=0.7, - max_tokens=50, - top_p=0.8, - stream=False, - system_prompt="System prompt", - model="gpt-4o-mini", - http_client_proxies=None, - http_async_client_proxies=None, - ) - yield config - - -def test_get_llm_model_answer(config, mocker): - mocked_get_answer = mocker.patch("embedchain.llm.openai.OpenAILlm._get_answer", return_value="Test answer") - - llm = OpenAILlm(config) - answer = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" - mocked_get_answer.assert_called_once_with("Test query", config) - - -def test_get_llm_model_answer_with_system_prompt(config, mocker): - config.system_prompt = "Custom system prompt" - mocked_get_answer = mocker.patch("embedchain.llm.openai.OpenAILlm._get_answer", return_value="Test answer") - - llm = OpenAILlm(config) - answer = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" - mocked_get_answer.assert_called_once_with("Test query", config) - - -def test_get_llm_model_answer_empty_prompt(config, mocker): - mocked_get_answer = mocker.patch("embedchain.llm.openai.OpenAILlm._get_answer", return_value="Test answer") - - llm = OpenAILlm(config) - answer = llm.get_llm_model_answer("") - - assert answer == "Test answer" - mocked_get_answer.assert_called_once_with("", config) - - -def test_get_llm_model_answer_with_token_usage(config, mocker): - test_config = BaseLlmConfig( - temperature=config.temperature, - max_tokens=config.max_tokens, - top_p=config.top_p, - stream=config.stream, - system_prompt=config.system_prompt, - model=config.model, - token_usage=True, - ) - mocked_get_answer = mocker.patch( - "embedchain.llm.openai.OpenAILlm._get_answer", - return_value=("Test answer", {"prompt_tokens": 1, "completion_tokens": 2}), - ) - - llm = OpenAILlm(test_config) - answer, token_info = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" - assert token_info == { - "prompt_tokens": 1, - "completion_tokens": 2, - "total_tokens": 3, - "total_cost": 1.35e-06, - "cost_currency": "USD", - } - mocked_get_answer.assert_called_once_with("Test query", test_config) - - -def test_get_llm_model_answer_with_streaming(config, mocker): - config.stream = True - mocked_openai_chat = mocker.patch("embedchain.llm.openai.ChatOpenAI") - - llm = OpenAILlm(config) - llm.get_llm_model_answer("Test query") - - mocked_openai_chat.assert_called_once() - callbacks = [callback[1]["callbacks"] for callback in mocked_openai_chat.call_args_list] - assert any(isinstance(callback[0], StreamingStdOutCallbackHandler) for callback in callbacks) - - -def test_get_llm_model_answer_without_system_prompt(config, mocker): - config.system_prompt = None - mocked_openai_chat = mocker.patch("embedchain.llm.openai.ChatOpenAI") - - llm = OpenAILlm(config) - llm.get_llm_model_answer("Test query") - - mocked_openai_chat.assert_called_once_with( - model=config.model, - temperature=config.temperature, - max_tokens=config.max_tokens, - model_kwargs={}, - top_p= config.top_p, - api_key=os.environ["OPENAI_API_KEY"], - base_url=os.environ["OPENAI_API_BASE"], - http_client=None, - http_async_client=None, - ) - - -def test_get_llm_model_answer_with_special_headers(config, mocker): - config.default_headers = {"test": "test"} - mocked_openai_chat = mocker.patch("embedchain.llm.openai.ChatOpenAI") - - llm = OpenAILlm(config) - llm.get_llm_model_answer("Test query") - - mocked_openai_chat.assert_called_once_with( - model=config.model, - temperature=config.temperature, - max_tokens=config.max_tokens, - model_kwargs={}, - top_p= config.top_p, - api_key=os.environ["OPENAI_API_KEY"], - base_url=os.environ["OPENAI_API_BASE"], - default_headers={"test": "test"}, - http_client=None, - http_async_client=None, - ) - - -def test_get_llm_model_answer_with_model_kwargs(config, mocker): - config.model_kwargs = {"response_format": {"type": "json_object"}} - mocked_openai_chat = mocker.patch("embedchain.llm.openai.ChatOpenAI") - - llm = OpenAILlm(config) - llm.get_llm_model_answer("Test query") - - mocked_openai_chat.assert_called_once_with( - model=config.model, - temperature=config.temperature, - max_tokens=config.max_tokens, - model_kwargs={"response_format": {"type": "json_object"}}, - top_p=config.top_p, - api_key=os.environ["OPENAI_API_KEY"], - base_url=os.environ["OPENAI_API_BASE"], - http_client=None, - http_async_client=None, - ) - - -@pytest.mark.parametrize( - "mock_return, expected", - [ - ([{"test": "test"}], '{"test": "test"}'), - ([], "Input could not be mapped to the function!"), - ], -) -def test_get_llm_model_answer_with_tools(config, mocker, mock_return, expected): - mocked_openai_chat = mocker.patch("embedchain.llm.openai.ChatOpenAI") - mocked_convert_to_openai_tool = mocker.patch("langchain_core.utils.function_calling.convert_to_openai_tool") - mocked_json_output_tools_parser = mocker.patch("langchain.output_parsers.openai_tools.JsonOutputToolsParser") - mocked_openai_chat.return_value.bind.return_value.pipe.return_value.invoke.return_value = mock_return - - llm = OpenAILlm(config, tools={"test": "test"}) - answer = llm.get_llm_model_answer("Test query") - - mocked_openai_chat.assert_called_once_with( - model=config.model, - temperature=config.temperature, - max_tokens=config.max_tokens, - model_kwargs={}, - top_p=config.top_p, - api_key=os.environ["OPENAI_API_KEY"], - base_url=os.environ["OPENAI_API_BASE"], - http_client=None, - http_async_client=None, - ) - mocked_convert_to_openai_tool.assert_called_once_with({"test": "test"}) - mocked_json_output_tools_parser.assert_called_once() - - assert answer == expected - - -def test_get_llm_model_answer_with_http_client_proxies(env_config, mocker): - mocked_openai_chat = mocker.patch("embedchain.llm.openai.ChatOpenAI") - mock_http_client = mocker.Mock(spec=httpx.Client) - mock_http_client_instance = mocker.Mock(spec=httpx.Client) - mock_http_client.return_value = mock_http_client_instance - - mocker.patch("httpx.Client", new=mock_http_client) - - config = BaseLlmConfig( - temperature=0.7, - max_tokens=50, - top_p=0.8, - stream=False, - system_prompt="System prompt", - model="gpt-4o-mini", - http_client_proxies="http://testproxy.mem0.net:8000", - ) - - llm = OpenAILlm(config) - llm.get_llm_model_answer("Test query") - - mocked_openai_chat.assert_called_once_with( - model=config.model, - temperature=config.temperature, - max_tokens=config.max_tokens, - model_kwargs={}, - top_p=config.top_p, - api_key=os.environ["OPENAI_API_KEY"], - base_url=os.environ["OPENAI_API_BASE"], - http_client=mock_http_client_instance, - http_async_client=None, - ) - mock_http_client.assert_called_once_with(proxies="http://testproxy.mem0.net:8000") - - -def test_get_llm_model_answer_with_http_async_client_proxies(env_config, mocker): - mocked_openai_chat = mocker.patch("embedchain.llm.openai.ChatOpenAI") - mock_http_async_client = mocker.Mock(spec=httpx.AsyncClient) - mock_http_async_client_instance = mocker.Mock(spec=httpx.AsyncClient) - mock_http_async_client.return_value = mock_http_async_client_instance - - mocker.patch("httpx.AsyncClient", new=mock_http_async_client) - - config = BaseLlmConfig( - temperature=0.7, - max_tokens=50, - top_p=0.8, - stream=False, - system_prompt="System prompt", - model="gpt-4o-mini", - http_async_client_proxies={"http://": "http://testproxy.mem0.net:8000"}, - ) - - llm = OpenAILlm(config) - llm.get_llm_model_answer("Test query") - - mocked_openai_chat.assert_called_once_with( - model=config.model, - temperature=config.temperature, - max_tokens=config.max_tokens, - model_kwargs={}, - top_p=config.top_p, - api_key=os.environ["OPENAI_API_KEY"], - base_url=os.environ["OPENAI_API_BASE"], - http_client=None, - http_async_client=mock_http_async_client_instance, - ) - mock_http_async_client.assert_called_once_with(proxies={"http://": "http://testproxy.mem0.net:8000"}) diff --git a/embedchain/tests/llm/test_query.py b/embedchain/tests/llm/test_query.py deleted file mode 100644 index 2472110e8..000000000 --- a/embedchain/tests/llm/test_query.py +++ /dev/null @@ -1,79 +0,0 @@ -import os -from unittest.mock import MagicMock, patch - -import pytest - -from embedchain import App -from embedchain.config import AppConfig, BaseLlmConfig -from embedchain.llm.openai import OpenAILlm - - -@pytest.fixture -def app(): - os.environ["OPENAI_API_KEY"] = "test_api_key" - app = App(config=AppConfig(collect_metrics=False)) - return app - - -@patch("chromadb.api.models.Collection.Collection.add", MagicMock) -def test_query(app): - with patch.object(app, "_retrieve_from_database") as mock_retrieve: - mock_retrieve.return_value = ["Test context"] - with patch.object(app.llm, "get_llm_model_answer") as mock_answer: - mock_answer.return_value = "Test answer" - answer = app.query(input_query="Test query") - assert answer == "Test answer" - - mock_retrieve.assert_called_once() - _, kwargs = mock_retrieve.call_args - input_query_arg = kwargs.get("input_query") - assert input_query_arg == "Test query" - mock_answer.assert_called_once() - - -@patch("embedchain.llm.openai.OpenAILlm._get_answer") -def test_query_config_app_passing(mock_get_answer): - mock_get_answer.return_value = MagicMock() - mock_get_answer.return_value = "Test answer" - - config = AppConfig(collect_metrics=False) - chat_config = BaseLlmConfig(system_prompt="Test system prompt") - llm = OpenAILlm(config=chat_config) - app = App(config=config, llm=llm) - answer = app.llm.get_llm_model_answer("Test query") - - assert app.llm.config.system_prompt == "Test system prompt" - assert answer == "Test answer" - - -@patch("chromadb.api.models.Collection.Collection.add", MagicMock) -def test_query_with_where_in_params(app): - with patch.object(app, "_retrieve_from_database") as mock_retrieve: - mock_retrieve.return_value = ["Test context"] - with patch.object(app.llm, "get_llm_model_answer") as mock_answer: - mock_answer.return_value = "Test answer" - answer = app.query("Test query", where={"attribute": "value"}) - - assert answer == "Test answer" - _, kwargs = mock_retrieve.call_args - assert kwargs.get("input_query") == "Test query" - assert kwargs.get("where") == {"attribute": "value"} - mock_answer.assert_called_once() - - -@patch("chromadb.api.models.Collection.Collection.add", MagicMock) -def test_query_with_where_in_query_config(app): - with patch.object(app.llm, "get_llm_model_answer") as mock_answer: - mock_answer.return_value = "Test answer" - with patch.object(app.db, "query") as mock_database_query: - mock_database_query.return_value = ["Test context"] - llm_config = BaseLlmConfig(where={"attribute": "value"}) - answer = app.query("Test query", llm_config) - - assert answer == "Test answer" - _, kwargs = mock_database_query.call_args - assert kwargs.get("input_query") == "Test query" - where = kwargs.get("where") - assert "app_id" in where - assert "attribute" in where - mock_answer.assert_called_once() diff --git a/embedchain/tests/llm/test_together.py b/embedchain/tests/llm/test_together.py deleted file mode 100644 index 3e8b566dd..000000000 --- a/embedchain/tests/llm/test_together.py +++ /dev/null @@ -1,74 +0,0 @@ -import os - -import pytest - -from embedchain.config import BaseLlmConfig -from embedchain.llm.together import TogetherLlm - - -@pytest.fixture -def together_llm_config(): - os.environ["TOGETHER_API_KEY"] = "test_api_key" - config = BaseLlmConfig(model="together-ai-up-to-3b", max_tokens=50, temperature=0.7, top_p=0.8) - yield config - os.environ.pop("TOGETHER_API_KEY") - - -def test_init_raises_value_error_without_api_key(mocker): - mocker.patch.dict(os.environ, clear=True) - with pytest.raises(ValueError): - TogetherLlm() - - -def test_get_llm_model_answer_raises_value_error_for_system_prompt(together_llm_config): - llm = TogetherLlm(together_llm_config) - llm.config.system_prompt = "system_prompt" - with pytest.raises(ValueError): - llm.get_llm_model_answer("prompt") - - -def test_get_llm_model_answer(together_llm_config, mocker): - mocker.patch("embedchain.llm.together.TogetherLlm._get_answer", return_value="Test answer") - - llm = TogetherLlm(together_llm_config) - answer = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" - - -def test_get_llm_model_answer_with_token_usage(together_llm_config, mocker): - test_config = BaseLlmConfig( - temperature=together_llm_config.temperature, - max_tokens=together_llm_config.max_tokens, - top_p=together_llm_config.top_p, - model=together_llm_config.model, - token_usage=True, - ) - mocker.patch( - "embedchain.llm.together.TogetherLlm._get_answer", - return_value=("Test answer", {"prompt_tokens": 1, "completion_tokens": 2}), - ) - - llm = TogetherLlm(test_config) - answer, token_info = llm.get_llm_model_answer("Test query") - - assert answer == "Test answer" - assert token_info == { - "prompt_tokens": 1, - "completion_tokens": 2, - "total_tokens": 3, - "total_cost": 3e-07, - "cost_currency": "USD", - } - - -def test_get_answer_mocked_together(together_llm_config, mocker): - mocked_together = mocker.patch("embedchain.llm.together.ChatTogether") - mock_instance = mocked_together.return_value - mock_instance.invoke.return_value.content = "Mocked answer" - - llm = TogetherLlm(together_llm_config) - prompt = "Test query" - answer = llm.get_llm_model_answer(prompt) - - assert answer == "Mocked answer" diff --git a/embedchain/tests/llm/test_vertex_ai.py b/embedchain/tests/llm/test_vertex_ai.py deleted file mode 100644 index 602c85a65..000000000 --- a/embedchain/tests/llm/test_vertex_ai.py +++ /dev/null @@ -1,76 +0,0 @@ -from unittest.mock import MagicMock, patch - -import pytest -from langchain.schema import HumanMessage, SystemMessage - -from embedchain.config import BaseLlmConfig -from embedchain.core.db.database import database_manager -from embedchain.llm.vertex_ai import VertexAILlm - - -@pytest.fixture(autouse=True) -def setup_database(): - database_manager.setup_engine() - - -@pytest.fixture -def vertexai_llm(): - config = BaseLlmConfig(temperature=0.6, model="chat-bison") - return VertexAILlm(config) - - -def test_get_llm_model_answer(vertexai_llm): - with patch.object(VertexAILlm, "_get_answer", return_value="Test Response") as mock_method: - prompt = "Test Prompt" - response = vertexai_llm.get_llm_model_answer(prompt) - assert response == "Test Response" - mock_method.assert_called_once_with(prompt, vertexai_llm.config) - - -def test_get_llm_model_answer_with_token_usage(vertexai_llm): - test_config = BaseLlmConfig( - temperature=vertexai_llm.config.temperature, - max_tokens=vertexai_llm.config.max_tokens, - top_p=vertexai_llm.config.top_p, - model=vertexai_llm.config.model, - token_usage=True, - ) - vertexai_llm.config = test_config - with patch.object( - VertexAILlm, - "_get_answer", - return_value=("Test Response", {"prompt_token_count": 1, "candidates_token_count": 2}), - ): - response, token_info = vertexai_llm.get_llm_model_answer("Test Query") - assert response == "Test Response" - assert token_info == { - "prompt_tokens": 1, - "completion_tokens": 2, - "total_tokens": 3, - "total_cost": 3.75e-07, - "cost_currency": "USD", - } - - -@patch("embedchain.llm.vertex_ai.ChatVertexAI") -def test_get_answer(mock_chat_vertexai, vertexai_llm, caplog): - mock_chat_vertexai.return_value.invoke.return_value = MagicMock(content="Test Response") - - config = vertexai_llm.config - prompt = "Test Prompt" - messages = vertexai_llm._get_messages(prompt) - response = vertexai_llm._get_answer(prompt, config) - mock_chat_vertexai.return_value.invoke.assert_called_once_with(messages) - - assert response == "Test Response" # Assertion corrected - assert "Config option `top_p` is not supported by this model." not in caplog.text - - -def test_get_messages(vertexai_llm): - prompt = "Test Prompt" - system_prompt = "Test System Prompt" - messages = vertexai_llm._get_messages(prompt, system_prompt) - assert messages == [ - SystemMessage(content="Test System Prompt", additional_kwargs={}), - HumanMessage(content="Test Prompt", additional_kwargs={}, example=False), - ] diff --git a/embedchain/tests/loaders/test_audio.py b/embedchain/tests/loaders/test_audio.py deleted file mode 100644 index c62ec1393..000000000 --- a/embedchain/tests/loaders/test_audio.py +++ /dev/null @@ -1,100 +0,0 @@ -import hashlib -import os -import sys -from unittest.mock import mock_open, patch - -import pytest - -if sys.version_info > (3, 10): # as `match` statement was introduced in python 3.10 - from deepgram import PrerecordedOptions - - from embedchain.loaders.audio import AudioLoader - - -@pytest.fixture -def setup_audio_loader(mocker): - mock_dropbox = mocker.patch("deepgram.DeepgramClient") - mock_dbx = mocker.MagicMock() - mock_dropbox.return_value = mock_dbx - - os.environ["DEEPGRAM_API_KEY"] = "test_key" - loader = AudioLoader() - loader.client = mock_dbx - - yield loader, mock_dbx - - if "DEEPGRAM_API_KEY" in os.environ: - del os.environ["DEEPGRAM_API_KEY"] - - -@pytest.mark.skipif( - sys.version_info < (3, 10), reason="Test skipped for Python 3.9 or lower" -) # as `match` statement was introduced in python 3.10 -def test_initialization(setup_audio_loader): - """Test initialization of AudioLoader.""" - loader, _ = setup_audio_loader - assert loader is not None - - -@pytest.mark.skipif( - sys.version_info < (3, 10), reason="Test skipped for Python 3.9 or lower" -) # as `match` statement was introduced in python 3.10 -def test_load_data_from_url(setup_audio_loader): - loader, mock_dbx = setup_audio_loader - url = "https://example.com/audio.mp3" - expected_content = "This is a test audio transcript." - - mock_response = {"results": {"channels": [{"alternatives": [{"transcript": expected_content}]}]}} - mock_dbx.listen.prerecorded.v.return_value.transcribe_url.return_value = mock_response - - result = loader.load_data(url) - - doc_id = hashlib.sha256((expected_content + url).encode()).hexdigest() - expected_result = { - "doc_id": doc_id, - "data": [ - { - "content": expected_content, - "meta_data": {"url": url}, - } - ], - } - - assert result == expected_result - mock_dbx.listen.prerecorded.v.assert_called_once_with("1") - mock_dbx.listen.prerecorded.v.return_value.transcribe_url.assert_called_once_with( - {"url": url}, PrerecordedOptions(model="nova-2", smart_format=True) - ) - - -@pytest.mark.skipif( - sys.version_info < (3, 10), reason="Test skipped for Python 3.9 or lower" -) # as `match` statement was introduced in python 3.10 -def test_load_data_from_file(setup_audio_loader): - loader, mock_dbx = setup_audio_loader - file_path = "local_audio.mp3" - expected_content = "This is a test audio transcript." - - mock_response = {"results": {"channels": [{"alternatives": [{"transcript": expected_content}]}]}} - mock_dbx.listen.prerecorded.v.return_value.transcribe_file.return_value = mock_response - - # Mock the file reading functionality - with patch("builtins.open", mock_open(read_data=b"some data")) as mock_file: - result = loader.load_data(file_path) - - doc_id = hashlib.sha256((expected_content + file_path).encode()).hexdigest() - expected_result = { - "doc_id": doc_id, - "data": [ - { - "content": expected_content, - "meta_data": {"url": file_path}, - } - ], - } - - assert result == expected_result - mock_dbx.listen.prerecorded.v.assert_called_once_with("1") - mock_dbx.listen.prerecorded.v.return_value.transcribe_file.assert_called_once_with( - {"buffer": mock_file.return_value}, PrerecordedOptions(model="nova-2", smart_format=True) - ) diff --git a/embedchain/tests/loaders/test_csv.py b/embedchain/tests/loaders/test_csv.py deleted file mode 100644 index 9cdcff394..000000000 --- a/embedchain/tests/loaders/test_csv.py +++ /dev/null @@ -1,113 +0,0 @@ -import csv -import os -import pathlib -import tempfile -from unittest.mock import MagicMock, patch - -import pytest - -from embedchain.loaders.csv import CsvLoader - - -@pytest.mark.parametrize("delimiter", [",", "\t", ";", "|"]) -def test_load_data(delimiter): - """ - Test csv loader - - Tests that file is loaded, metadata is correct and content is correct - """ - # Creating temporary CSV file - with tempfile.NamedTemporaryFile(mode="w+", newline="", delete=False) as tmpfile: - writer = csv.writer(tmpfile, delimiter=delimiter) - writer.writerow(["Name", "Age", "Occupation"]) - writer.writerow(["Alice", "28", "Engineer"]) - writer.writerow(["Bob", "35", "Doctor"]) - writer.writerow(["Charlie", "22", "Student"]) - - tmpfile.seek(0) - filename = tmpfile.name - - # Loading CSV using CsvLoader - loader = CsvLoader() - result = loader.load_data(filename) - data = result["data"] - - # Assertions - assert len(data) == 3 - assert data[0]["content"] == "Name: Alice, Age: 28, Occupation: Engineer" - assert data[0]["meta_data"]["url"] == filename - assert data[0]["meta_data"]["row"] == 1 - assert data[1]["content"] == "Name: Bob, Age: 35, Occupation: Doctor" - assert data[1]["meta_data"]["url"] == filename - assert data[1]["meta_data"]["row"] == 2 - assert data[2]["content"] == "Name: Charlie, Age: 22, Occupation: Student" - assert data[2]["meta_data"]["url"] == filename - assert data[2]["meta_data"]["row"] == 3 - - # Cleaning up the temporary file - os.unlink(filename) - - -@pytest.mark.parametrize("delimiter", [",", "\t", ";", "|"]) -def test_load_data_with_file_uri(delimiter): - """ - Test csv loader with file URI - - Tests that file is loaded, metadata is correct and content is correct - """ - # Creating temporary CSV file - with tempfile.NamedTemporaryFile(mode="w+", newline="", delete=False) as tmpfile: - writer = csv.writer(tmpfile, delimiter=delimiter) - writer.writerow(["Name", "Age", "Occupation"]) - writer.writerow(["Alice", "28", "Engineer"]) - writer.writerow(["Bob", "35", "Doctor"]) - writer.writerow(["Charlie", "22", "Student"]) - - tmpfile.seek(0) - filename = pathlib.Path(tmpfile.name).as_uri() # Convert path to file URI - - # Loading CSV using CsvLoader - loader = CsvLoader() - result = loader.load_data(filename) - data = result["data"] - - # Assertions - assert len(data) == 3 - assert data[0]["content"] == "Name: Alice, Age: 28, Occupation: Engineer" - assert data[0]["meta_data"]["url"] == filename - assert data[0]["meta_data"]["row"] == 1 - assert data[1]["content"] == "Name: Bob, Age: 35, Occupation: Doctor" - assert data[1]["meta_data"]["url"] == filename - assert data[1]["meta_data"]["row"] == 2 - assert data[2]["content"] == "Name: Charlie, Age: 22, Occupation: Student" - assert data[2]["meta_data"]["url"] == filename - assert data[2]["meta_data"]["row"] == 3 - - # Cleaning up the temporary file - os.unlink(tmpfile.name) - - -@pytest.mark.parametrize("content", ["ftp://example.com", "sftp://example.com", "mailto://example.com"]) -def test_get_file_content(content): - with pytest.raises(ValueError): - loader = CsvLoader() - loader._get_file_content(content) - - -@pytest.mark.parametrize("content", ["http://example.com", "https://example.com"]) -def test_get_file_content_http(content): - """ - Test _get_file_content method of CsvLoader for http and https URLs - """ - - with patch("requests.get") as mock_get: - mock_response = MagicMock() - mock_response.text = "Name,Age,Occupation\nAlice,28,Engineer\nBob,35,Doctor\nCharlie,22,Student" - mock_get.return_value = mock_response - - loader = CsvLoader() - file_content = loader._get_file_content(content) - - mock_get.assert_called_once_with(content) - mock_response.raise_for_status.assert_called_once() - assert file_content.read() == mock_response.text diff --git a/embedchain/tests/loaders/test_discourse.py b/embedchain/tests/loaders/test_discourse.py deleted file mode 100644 index 71635b377..000000000 --- a/embedchain/tests/loaders/test_discourse.py +++ /dev/null @@ -1,104 +0,0 @@ -import pytest -import requests - -from embedchain.loaders.discourse import DiscourseLoader - - -@pytest.fixture -def discourse_loader_config(): - return { - "domain": "https://example.com/", - } - - -@pytest.fixture -def discourse_loader(discourse_loader_config): - return DiscourseLoader(config=discourse_loader_config) - - -def test_discourse_loader_init_with_valid_config(): - config = {"domain": "https://example.com/"} - loader = DiscourseLoader(config=config) - assert loader.domain == "https://example.com/" - - -def test_discourse_loader_init_with_missing_config(): - with pytest.raises(ValueError, match="DiscourseLoader requires a config"): - DiscourseLoader() - - -def test_discourse_loader_init_with_missing_domain(): - config = {"another_key": "value"} - with pytest.raises(ValueError, match="DiscourseLoader requires a domain"): - DiscourseLoader(config=config) - - -def test_discourse_loader_check_query_with_valid_query(discourse_loader): - discourse_loader._check_query("sample query") - - -def test_discourse_loader_check_query_with_empty_query(discourse_loader): - with pytest.raises(ValueError, match="DiscourseLoader requires a query"): - discourse_loader._check_query("") - - -def test_discourse_loader_check_query_with_invalid_query_type(discourse_loader): - with pytest.raises(ValueError, match="DiscourseLoader requires a query"): - discourse_loader._check_query(123) - - -def test_discourse_loader_load_post_with_valid_post_id(discourse_loader, monkeypatch): - def mock_get(*args, **kwargs): - class MockResponse: - def json(self): - return {"raw": "Sample post content"} - - def raise_for_status(self): - pass - - return MockResponse() - - monkeypatch.setattr(requests, "get", mock_get) - - post_data = discourse_loader._load_post(123) - - assert post_data["content"] == "Sample post content" - assert "meta_data" in post_data - - -def test_discourse_loader_load_data_with_valid_query(discourse_loader, monkeypatch): - def mock_get(*args, **kwargs): - class MockResponse: - def json(self): - return {"grouped_search_result": {"post_ids": [123, 456, 789]}} - - def raise_for_status(self): - pass - - return MockResponse() - - monkeypatch.setattr(requests, "get", mock_get) - - def mock_load_post(*args, **kwargs): - return { - "content": "Sample post content", - "meta_data": { - "url": "https://example.com/posts/123.json", - "created_at": "2021-01-01", - "username": "test_user", - "topic_slug": "test_topic", - "score": 10, - }, - } - - monkeypatch.setattr(discourse_loader, "_load_post", mock_load_post) - - data = discourse_loader.load_data("sample query") - - assert len(data["data"]) == 3 - assert data["data"][0]["content"] == "Sample post content" - assert data["data"][0]["meta_data"]["url"] == "https://example.com/posts/123.json" - assert data["data"][0]["meta_data"]["created_at"] == "2021-01-01" - assert data["data"][0]["meta_data"]["username"] == "test_user" - assert data["data"][0]["meta_data"]["topic_slug"] == "test_topic" - assert data["data"][0]["meta_data"]["score"] == 10 diff --git a/embedchain/tests/loaders/test_docs_site.py b/embedchain/tests/loaders/test_docs_site.py deleted file mode 100644 index 31d03f67a..000000000 --- a/embedchain/tests/loaders/test_docs_site.py +++ /dev/null @@ -1,130 +0,0 @@ -import hashlib -from unittest.mock import Mock, patch - -import pytest -from requests import Response - -from embedchain.loaders.docs_site_loader import DocsSiteLoader - - -@pytest.fixture -def mock_requests_get(): - with patch("requests.get") as mock_get: - yield mock_get - - -@pytest.fixture -def docs_site_loader(): - return DocsSiteLoader() - - -def test_get_child_links_recursive(mock_requests_get, docs_site_loader): - mock_response = Mock() - mock_response.status_code = 200 - mock_response.text = """ - - Page 1 - Page 2 - - """ - mock_requests_get.return_value = mock_response - - docs_site_loader._get_child_links_recursive("https://example.com") - - assert len(docs_site_loader.visited_links) == 2 - assert "https://example.com/page1" in docs_site_loader.visited_links - assert "https://example.com/page2" in docs_site_loader.visited_links - - -def test_get_child_links_recursive_status_not_200(mock_requests_get, docs_site_loader): - mock_response = Mock() - mock_response.status_code = 404 - mock_requests_get.return_value = mock_response - - docs_site_loader._get_child_links_recursive("https://example.com") - - assert len(docs_site_loader.visited_links) == 0 - - -def test_get_all_urls(mock_requests_get, docs_site_loader): - mock_response = Mock() - mock_response.status_code = 200 - mock_response.text = """ - - Page 1 - Page 2 - External - - """ - mock_requests_get.return_value = mock_response - - all_urls = docs_site_loader._get_all_urls("https://example.com") - - assert len(all_urls) == 3 - assert "https://example.com/page1" in all_urls - assert "https://example.com/page2" in all_urls - assert "https://example.com/external" in all_urls - - -def test_load_data_from_url(mock_requests_get, docs_site_loader): - mock_response = Mock() - mock_response.status_code = 200 - mock_response.content = """ - - -
-

Article Content

-
- - """.encode() - mock_requests_get.return_value = mock_response - - data = docs_site_loader._load_data_from_url("https://example.com/page1") - - assert len(data) == 1 - assert data[0]["content"] == "Article Content" - assert data[0]["meta_data"]["url"] == "https://example.com/page1" - - -def test_load_data_from_url_status_not_200(mock_requests_get, docs_site_loader): - mock_response = Mock() - mock_response.status_code = 404 - mock_requests_get.return_value = mock_response - - data = docs_site_loader._load_data_from_url("https://example.com/page1") - - assert data == [] - assert len(data) == 0 - - -def test_load_data(mock_requests_get, docs_site_loader): - mock_response = Response() - mock_response.status_code = 200 - mock_response._content = """ - - Page 1 - Page 2 - """.encode() - mock_requests_get.return_value = mock_response - - url = "https://example.com" - data = docs_site_loader.load_data(url) - expected_doc_id = hashlib.sha256((" ".join(docs_site_loader.visited_links) + url).encode()).hexdigest() - - assert len(data["data"]) == 2 - assert data["doc_id"] == expected_doc_id - - -def test_if_response_status_not_200(mock_requests_get, docs_site_loader): - mock_response = Response() - mock_response.status_code = 404 - mock_requests_get.return_value = mock_response - - url = "https://example.com" - data = docs_site_loader.load_data(url) - expected_doc_id = hashlib.sha256((" ".join(docs_site_loader.visited_links) + url).encode()).hexdigest() - - assert len(data["data"]) == 0 - assert data["doc_id"] == expected_doc_id diff --git a/embedchain/tests/loaders/test_docs_site_loader.py b/embedchain/tests/loaders/test_docs_site_loader.py deleted file mode 100644 index 16b503b9f..000000000 --- a/embedchain/tests/loaders/test_docs_site_loader.py +++ /dev/null @@ -1,218 +0,0 @@ -import pytest -import responses -from bs4 import BeautifulSoup - - -@pytest.mark.parametrize( - "ignored_tag", - [ - "", - "", - "
This is a form.
", - "
This is a header.
", - "", - "This is an SVG.", - "This is a canvas.", - "
This is a footer.
", - "", - "", - ], - ids=["nav", "aside", "form", "header", "noscript", "svg", "canvas", "footer", "script", "style"], -) -@pytest.mark.parametrize( - "selectee", - [ - """ -
-

Article Title

-

Article content goes here.

- {ignored_tag} -
-""", - """ -
-

Main Article Title

-

Main article content goes here.

- {ignored_tag} -
-""", - """ -
-

Markdown Content

-

Markdown content goes here.

- {ignored_tag} -
-""", - """ -
-

Main Content

-

Main content goes here.

- {ignored_tag} -
-""", - """ -
-

Container

-

Container content goes here.

- {ignored_tag} -
- """, - """ -
-

Section

-

Section content goes here.

- {ignored_tag} -
- """, - """ -
-

Generic Article

-

Generic article content goes here.

- {ignored_tag} -
- """, - """ -
-

Main Content

-

Main content goes here.

- {ignored_tag} -
-""", - ], - ids=[ - "article.bd-article", - 'article[role="main"]', - "div.md-content", - 'div[role="main"]', - "div.container", - "div.section", - "article", - "main", - ], -) -def test_load_data_gets_by_selectors_and_ignored_tags(selectee, ignored_tag, loader, mocked_responses, mocker): - child_url = "https://docs.embedchain.ai/quickstart" - selectee = selectee.format(ignored_tag=ignored_tag) - html_body = """ - - - - {selectee} - - -""" - html_body = html_body.format(selectee=selectee) - mocked_responses.get(child_url, body=html_body, status=200, content_type="text/html") - - url = "https://docs.embedchain.ai/" - html_body = """ - - - -
  • Quickstart
  • - - -""" - mocked_responses.get(url, body=html_body, status=200, content_type="text/html") - - mock_sha256 = mocker.patch("embedchain.loaders.docs_site_loader.hashlib.sha256") - doc_id = "mocked_hash" - mock_sha256.return_value.hexdigest.return_value = doc_id - - result = loader.load_data(url) - selector_soup = BeautifulSoup(selectee, "html.parser") - expected_content = " ".join((selector_soup.select_one("h2").get_text(), selector_soup.select_one("p").get_text())) - assert result["doc_id"] == doc_id - assert result["data"] == [ - { - "content": expected_content, - "meta_data": {"url": "https://docs.embedchain.ai/quickstart"}, - } - ] - - -def test_load_data_gets_child_links_recursively(loader, mocked_responses, mocker): - child_url = "https://docs.embedchain.ai/quickstart" - html_body = """ - - - -
  • ..
  • -
  • .
  • - - -""" - mocked_responses.get(child_url, body=html_body, status=200, content_type="text/html") - - child_url = "https://docs.embedchain.ai/introduction" - html_body = """ - - - -
  • ..
  • -
  • .
  • - - -""" - mocked_responses.get(child_url, body=html_body, status=200, content_type="text/html") - - url = "https://docs.embedchain.ai/" - html_body = """ - - - -
  • Quickstart
  • -
  • Introduction
  • - - -""" - mocked_responses.get(url, body=html_body, status=200, content_type="text/html") - - mock_sha256 = mocker.patch("embedchain.loaders.docs_site_loader.hashlib.sha256") - doc_id = "mocked_hash" - mock_sha256.return_value.hexdigest.return_value = doc_id - - result = loader.load_data(url) - assert result["doc_id"] == doc_id - expected_data = [ - {"content": "..\n.", "meta_data": {"url": "https://docs.embedchain.ai/quickstart"}}, - {"content": "..\n.", "meta_data": {"url": "https://docs.embedchain.ai/introduction"}}, - ] - assert all(item in expected_data for item in result["data"]) - - -def test_load_data_fails_to_fetch_website(loader, mocked_responses, mocker): - child_url = "https://docs.embedchain.ai/introduction" - mocked_responses.get(child_url, status=404) - - url = "https://docs.embedchain.ai/" - html_body = """ - - - -
  • Introduction
  • - - -""" - mocked_responses.get(url, body=html_body, status=200, content_type="text/html") - - mock_sha256 = mocker.patch("embedchain.loaders.docs_site_loader.hashlib.sha256") - doc_id = "mocked_hash" - mock_sha256.return_value.hexdigest.return_value = doc_id - - result = loader.load_data(url) - assert result["doc_id"] is doc_id - assert result["data"] == [] - - -@pytest.fixture -def loader(): - from embedchain.loaders.docs_site_loader import DocsSiteLoader - - return DocsSiteLoader() - - -@pytest.fixture -def mocked_responses(): - with responses.RequestsMock() as rsps: - yield rsps diff --git a/embedchain/tests/loaders/test_docx_file.py b/embedchain/tests/loaders/test_docx_file.py deleted file mode 100644 index b7deffcb2..000000000 --- a/embedchain/tests/loaders/test_docx_file.py +++ /dev/null @@ -1,39 +0,0 @@ -import hashlib -from unittest.mock import MagicMock, patch - -import pytest - -from embedchain.loaders.docx_file import DocxFileLoader - - -@pytest.fixture -def mock_docx2txt_loader(): - with patch("embedchain.loaders.docx_file.Docx2txtLoader") as mock_loader: - yield mock_loader - - -@pytest.fixture -def docx_file_loader(): - return DocxFileLoader() - - -def test_load_data(mock_docx2txt_loader, docx_file_loader): - mock_url = "mock_docx_file.docx" - - mock_loader = MagicMock() - mock_loader.load.return_value = [MagicMock(page_content="Sample Docx Content", metadata={"url": "local"})] - - mock_docx2txt_loader.return_value = mock_loader - - result = docx_file_loader.load_data(mock_url) - - assert "doc_id" in result - assert "data" in result - - expected_content = "Sample Docx Content" - assert result["data"][0]["content"] == expected_content - - assert result["data"][0]["meta_data"]["url"] == "local" - - expected_doc_id = hashlib.sha256((expected_content + mock_url).encode()).hexdigest() - assert result["doc_id"] == expected_doc_id diff --git a/embedchain/tests/loaders/test_dropbox.py b/embedchain/tests/loaders/test_dropbox.py deleted file mode 100644 index c7e816731..000000000 --- a/embedchain/tests/loaders/test_dropbox.py +++ /dev/null @@ -1,85 +0,0 @@ -import os -from unittest.mock import MagicMock - -import pytest -from dropbox.files import FileMetadata - -from embedchain.loaders.dropbox import DropboxLoader - - -@pytest.fixture -def setup_dropbox_loader(mocker): - mock_dropbox = mocker.patch("dropbox.Dropbox") - mock_dbx = mocker.MagicMock() - mock_dropbox.return_value = mock_dbx - - os.environ["DROPBOX_ACCESS_TOKEN"] = "test_token" - loader = DropboxLoader() - - yield loader, mock_dbx - - if "DROPBOX_ACCESS_TOKEN" in os.environ: - del os.environ["DROPBOX_ACCESS_TOKEN"] - - -def test_initialization(setup_dropbox_loader): - """Test initialization of DropboxLoader.""" - loader, _ = setup_dropbox_loader - assert loader is not None - - -def test_download_folder(setup_dropbox_loader, mocker): - """Test downloading a folder.""" - loader, mock_dbx = setup_dropbox_loader - mocker.patch("os.makedirs") - mocker.patch("os.path.join", return_value="mock/path") - - mock_file_metadata = mocker.MagicMock(spec=FileMetadata) - mock_dbx.files_list_folder.return_value.entries = [mock_file_metadata] - - entries = loader._download_folder("path/to/folder", "local_root") - assert entries is not None - - -def test_generate_dir_id_from_all_paths(setup_dropbox_loader, mocker): - """Test directory ID generation.""" - loader, mock_dbx = setup_dropbox_loader - mock_file_metadata = mocker.MagicMock(spec=FileMetadata, name="file.txt") - mock_dbx.files_list_folder.return_value.entries = [mock_file_metadata] - - dir_id = loader._generate_dir_id_from_all_paths("path/to/folder") - assert dir_id is not None - assert len(dir_id) == 64 - - -def test_clean_directory(setup_dropbox_loader, mocker): - """Test cleaning up a directory.""" - loader, _ = setup_dropbox_loader - mocker.patch("os.listdir", return_value=["file1", "file2"]) - mocker.patch("os.remove") - mocker.patch("os.rmdir") - - loader._clean_directory("path/to/folder") - - -def test_load_data(mocker, setup_dropbox_loader, tmp_path): - loader = setup_dropbox_loader[0] - - mock_file_metadata = MagicMock(spec=FileMetadata, name="file.txt") - mocker.patch.object(loader.dbx, "files_list_folder", return_value=MagicMock(entries=[mock_file_metadata])) - mocker.patch.object(loader.dbx, "files_download_to_file") - - # Mock DirectoryLoader - mock_data = {"data": "test_data"} - mocker.patch("embedchain.loaders.directory_loader.DirectoryLoader.load_data", return_value=mock_data) - - test_dir = tmp_path / "dropbox_test" - test_dir.mkdir() - test_file = test_dir / "file.txt" - test_file.write_text("dummy content") - mocker.patch.object(loader, "_generate_dir_id_from_all_paths", return_value=str(test_dir)) - - result = loader.load_data("path/to/folder") - - assert result == {"doc_id": mocker.ANY, "data": "test_data"} - loader.dbx.files_list_folder.assert_called_once_with("path/to/folder") diff --git a/embedchain/tests/loaders/test_excel_file.py b/embedchain/tests/loaders/test_excel_file.py deleted file mode 100644 index c0865ed5e..000000000 --- a/embedchain/tests/loaders/test_excel_file.py +++ /dev/null @@ -1,33 +0,0 @@ -import hashlib -from unittest.mock import patch - -import pytest - -from embedchain.loaders.excel_file import ExcelFileLoader - - -@pytest.fixture -def excel_file_loader(): - return ExcelFileLoader() - - -def test_load_data(excel_file_loader): - mock_url = "mock_excel_file.xlsx" - expected_content = "Sample Excel Content" - - # Mock the load_data method of the excel_file_loader instance - with patch.object( - excel_file_loader, - "load_data", - return_value={ - "doc_id": hashlib.sha256((expected_content + mock_url).encode()).hexdigest(), - "data": [{"content": expected_content, "meta_data": {"url": mock_url}}], - }, - ): - result = excel_file_loader.load_data(mock_url) - - assert result["data"][0]["content"] == expected_content - assert result["data"][0]["meta_data"]["url"] == mock_url - - expected_doc_id = hashlib.sha256((expected_content + mock_url).encode()).hexdigest() - assert result["doc_id"] == expected_doc_id diff --git a/embedchain/tests/loaders/test_github.py b/embedchain/tests/loaders/test_github.py deleted file mode 100644 index fe728a89b..000000000 --- a/embedchain/tests/loaders/test_github.py +++ /dev/null @@ -1,33 +0,0 @@ -import pytest - -from embedchain.loaders.github import GithubLoader - - -@pytest.fixture -def mock_github_loader_config(): - return { - "token": "your_mock_token", - } - - -@pytest.fixture -def mock_github_loader(mocker, mock_github_loader_config): - mock_github = mocker.patch("github.Github") - _ = mock_github.return_value - return GithubLoader(config=mock_github_loader_config) - - -def test_github_loader_init(mocker, mock_github_loader_config): - mock_github = mocker.patch("github.Github") - GithubLoader(config=mock_github_loader_config) - mock_github.assert_called_once_with("your_mock_token") - - -def test_github_loader_init_empty_config(mocker): - with pytest.raises(ValueError, match="requires a personal access token"): - GithubLoader() - - -def test_github_loader_init_missing_token(): - with pytest.raises(ValueError, match="requires a personal access token"): - GithubLoader(config={}) diff --git a/embedchain/tests/loaders/test_gmail.py b/embedchain/tests/loaders/test_gmail.py deleted file mode 100644 index 1b7834b87..000000000 --- a/embedchain/tests/loaders/test_gmail.py +++ /dev/null @@ -1,43 +0,0 @@ -import pytest - -from embedchain.loaders.gmail import GmailLoader - - -@pytest.fixture -def mock_beautifulsoup(mocker): - return mocker.patch("embedchain.loaders.gmail.BeautifulSoup", return_value=mocker.MagicMock()) - - -@pytest.fixture -def gmail_loader(mock_beautifulsoup): - return GmailLoader() - - -def test_load_data_file_not_found(gmail_loader, mocker): - with pytest.raises(FileNotFoundError): - with mocker.patch("os.path.isfile", return_value=False): - gmail_loader.load_data("your_query") - - -@pytest.mark.skip(reason="TODO: Fix this test. Failing due to some googleapiclient import issue.") -def test_load_data(gmail_loader, mocker): - mock_gmail_reader_instance = mocker.MagicMock() - text = "your_test_email_text" - metadata = { - "id": "your_test_id", - "snippet": "your_test_snippet", - } - mock_gmail_reader_instance.load_data.return_value = [ - { - "text": text, - "extra_info": metadata, - } - ] - - with mocker.patch("os.path.isfile", return_value=True): - response_data = gmail_loader.load_data("your_query") - - assert "doc_id" in response_data - assert "data" in response_data - assert isinstance(response_data["doc_id"], str) - assert isinstance(response_data["data"], list) diff --git a/embedchain/tests/loaders/test_google_drive.py b/embedchain/tests/loaders/test_google_drive.py deleted file mode 100644 index 00d8bb1c1..000000000 --- a/embedchain/tests/loaders/test_google_drive.py +++ /dev/null @@ -1,37 +0,0 @@ -import pytest - -from embedchain.loaders.google_drive import GoogleDriveLoader - - -@pytest.fixture -def google_drive_folder_loader(): - return GoogleDriveLoader() - - -def test_load_data_invalid_drive_url(google_drive_folder_loader): - mock_invalid_drive_url = "https://example.com" - with pytest.raises( - ValueError, - match="The url provided https://example.com does not match a google drive folder url. Example " - "drive url: https://drive.google.com/drive/u/0/folders/xxxx", - ): - google_drive_folder_loader.load_data(mock_invalid_drive_url) - - -@pytest.mark.skip(reason="This test won't work unless google api credentials are properly setup.") -def test_load_data_incorrect_drive_url(google_drive_folder_loader): - mock_invalid_drive_url = "https://drive.google.com/drive/u/0/folders/xxxx" - with pytest.raises( - FileNotFoundError, match="Unable to locate folder or files, check provided drive URL and try again" - ): - google_drive_folder_loader.load_data(mock_invalid_drive_url) - - -@pytest.mark.skip(reason="This test won't work unless google api credentials are properly setup.") -def test_load_data(google_drive_folder_loader): - mock_valid_url = "YOUR_VALID_URL" - result = google_drive_folder_loader.load_data(mock_valid_url) - assert "doc_id" in result - assert "data" in result - assert "content" in result["data"][0] - assert "meta_data" in result["data"][0] diff --git a/embedchain/tests/loaders/test_json.py b/embedchain/tests/loaders/test_json.py deleted file mode 100644 index ba2361407..000000000 --- a/embedchain/tests/loaders/test_json.py +++ /dev/null @@ -1,131 +0,0 @@ -import hashlib - -import pytest - -from embedchain.loaders.json import JSONLoader - - -def test_load_data(mocker): - content = "temp.json" - - mock_document = { - "doc_id": hashlib.sha256((content + ", ".join(["content1", "content2"])).encode()).hexdigest(), - "data": [ - {"content": "content1", "meta_data": {"url": content}}, - {"content": "content2", "meta_data": {"url": content}}, - ], - } - - mocker.patch("embedchain.loaders.json.JSONLoader.load_data", return_value=mock_document) - - json_loader = JSONLoader() - - result = json_loader.load_data(content) - - assert "doc_id" in result - assert "data" in result - - expected_data = [ - {"content": "content1", "meta_data": {"url": content}}, - {"content": "content2", "meta_data": {"url": content}}, - ] - - assert result["data"] == expected_data - - expected_doc_id = hashlib.sha256((content + ", ".join(["content1", "content2"])).encode()).hexdigest() - assert result["doc_id"] == expected_doc_id - - -def test_load_data_url(mocker): - content = "https://example.com/posts.json" - - mocker.patch("os.path.isfile", return_value=False) - mocker.patch( - "embedchain.loaders.json.JSONReader.load_data", - return_value=[ - { - "text": "content1", - }, - { - "text": "content2", - }, - ], - ) - - mock_response = mocker.Mock() - mock_response.status_code = 200 - mock_response.json.return_value = {"document1": "content1", "document2": "content2"} - - mocker.patch("requests.get", return_value=mock_response) - - result = JSONLoader.load_data(content) - - assert "doc_id" in result - assert "data" in result - - expected_data = [ - {"content": "content1", "meta_data": {"url": content}}, - {"content": "content2", "meta_data": {"url": content}}, - ] - - assert result["data"] == expected_data - - expected_doc_id = hashlib.sha256((content + ", ".join(["content1", "content2"])).encode()).hexdigest() - assert result["doc_id"] == expected_doc_id - - -def test_load_data_invalid_string_content(mocker): - mocker.patch("os.path.isfile", return_value=False) - mocker.patch("requests.get") - - content = "123: 345}" - - with pytest.raises(ValueError, match="Invalid content to load json data from"): - JSONLoader.load_data(content) - - -def test_load_data_invalid_url(mocker): - mocker.patch("os.path.isfile", return_value=False) - - mock_response = mocker.Mock() - mock_response.status_code = 404 - mocker.patch("requests.get", return_value=mock_response) - - content = "http://invalid-url.com/" - - with pytest.raises(ValueError, match=f"Invalid content to load json data from: {content}"): - JSONLoader.load_data(content) - - -def test_load_data_from_json_string(mocker): - content = '{"foo": "bar"}' - - content_url_str = hashlib.sha256((content).encode("utf-8")).hexdigest() - - mocker.patch("os.path.isfile", return_value=False) - mocker.patch( - "embedchain.loaders.json.JSONReader.load_data", - return_value=[ - { - "text": "content1", - }, - { - "text": "content2", - }, - ], - ) - - result = JSONLoader.load_data(content) - - assert "doc_id" in result - assert "data" in result - - expected_data = [ - {"content": "content1", "meta_data": {"url": content_url_str}}, - {"content": "content2", "meta_data": {"url": content_url_str}}, - ] - - assert result["data"] == expected_data - - expected_doc_id = hashlib.sha256((content_url_str + ", ".join(["content1", "content2"])).encode()).hexdigest() - assert result["doc_id"] == expected_doc_id diff --git a/embedchain/tests/loaders/test_local_qna_pair.py b/embedchain/tests/loaders/test_local_qna_pair.py deleted file mode 100644 index 5bdfd2caf..000000000 --- a/embedchain/tests/loaders/test_local_qna_pair.py +++ /dev/null @@ -1,32 +0,0 @@ -import hashlib - -import pytest - -from embedchain.loaders.local_qna_pair import LocalQnaPairLoader - - -@pytest.fixture -def qna_pair_loader(): - return LocalQnaPairLoader() - - -def test_load_data(qna_pair_loader): - question = "What is the capital of France?" - answer = "The capital of France is Paris." - - content = (question, answer) - result = qna_pair_loader.load_data(content) - - assert "doc_id" in result - assert "data" in result - url = "local" - - expected_content = f"Q: {question}\nA: {answer}" - assert result["data"][0]["content"] == expected_content - - assert result["data"][0]["meta_data"]["url"] == url - - assert result["data"][0]["meta_data"]["question"] == question - - expected_doc_id = hashlib.sha256((expected_content + url).encode()).hexdigest() - assert result["doc_id"] == expected_doc_id diff --git a/embedchain/tests/loaders/test_local_text.py b/embedchain/tests/loaders/test_local_text.py deleted file mode 100644 index 58b6ec8fe..000000000 --- a/embedchain/tests/loaders/test_local_text.py +++ /dev/null @@ -1,27 +0,0 @@ -import hashlib - -import pytest - -from embedchain.loaders.local_text import LocalTextLoader - - -@pytest.fixture -def text_loader(): - return LocalTextLoader() - - -def test_load_data(text_loader): - mock_content = "This is a sample text content." - - result = text_loader.load_data(mock_content) - - assert "doc_id" in result - assert "data" in result - - url = "local" - assert result["data"][0]["content"] == mock_content - - assert result["data"][0]["meta_data"]["url"] == url - - expected_doc_id = hashlib.sha256((mock_content + url).encode()).hexdigest() - assert result["doc_id"] == expected_doc_id diff --git a/embedchain/tests/loaders/test_mdx.py b/embedchain/tests/loaders/test_mdx.py deleted file mode 100644 index d4826209b..000000000 --- a/embedchain/tests/loaders/test_mdx.py +++ /dev/null @@ -1,30 +0,0 @@ -import hashlib -from unittest.mock import mock_open, patch - -import pytest - -from embedchain.loaders.mdx import MdxLoader - - -@pytest.fixture -def mdx_loader(): - return MdxLoader() - - -def test_load_data(mdx_loader): - mock_content = "Sample MDX Content" - - # Mock open function to simulate file reading - with patch("builtins.open", mock_open(read_data=mock_content)): - url = "mock_file.mdx" - result = mdx_loader.load_data(url) - - assert "doc_id" in result - assert "data" in result - - assert result["data"][0]["content"] == mock_content - - assert result["data"][0]["meta_data"]["url"] == url - - expected_doc_id = hashlib.sha256((mock_content + url).encode()).hexdigest() - assert result["doc_id"] == expected_doc_id diff --git a/embedchain/tests/loaders/test_mysql.py b/embedchain/tests/loaders/test_mysql.py deleted file mode 100644 index 976d30ff8..000000000 --- a/embedchain/tests/loaders/test_mysql.py +++ /dev/null @@ -1,77 +0,0 @@ -import hashlib -from unittest.mock import MagicMock - -import pytest - -from embedchain.loaders.mysql import MySQLLoader - - -@pytest.fixture -def mysql_loader(mocker): - with mocker.patch("mysql.connector.connection.MySQLConnection"): - config = { - "host": "localhost", - "port": "3306", - "user": "your_username", - "password": "your_password", - "database": "your_database", - } - loader = MySQLLoader(config=config) - yield loader - - -def test_mysql_loader_initialization(mysql_loader): - assert mysql_loader.config is not None - assert mysql_loader.connection is not None - assert mysql_loader.cursor is not None - - -def test_mysql_loader_invalid_config(): - with pytest.raises(ValueError, match="Invalid sql config: None"): - MySQLLoader(config=None) - - -def test_mysql_loader_setup_loader_successful(mysql_loader): - assert mysql_loader.connection is not None - assert mysql_loader.cursor is not None - - -def test_mysql_loader_setup_loader_connection_error(mysql_loader, mocker): - mocker.patch("mysql.connector.connection.MySQLConnection", side_effect=IOError("Mocked connection error")) - with pytest.raises(ValueError, match="Unable to connect with the given config:"): - mysql_loader._setup_loader(config={}) - - -def test_mysql_loader_check_query_successful(mysql_loader): - query = "SELECT * FROM table" - mysql_loader._check_query(query=query) - - -def test_mysql_loader_check_query_invalid(mysql_loader): - with pytest.raises(ValueError, match="Invalid mysql query: 123"): - mysql_loader._check_query(query=123) - - -def test_mysql_loader_load_data_successful(mysql_loader, mocker): - mock_cursor = MagicMock() - mocker.patch.object(mysql_loader, "cursor", mock_cursor) - mock_cursor.fetchall.return_value = [(1, "data1"), (2, "data2")] - - query = "SELECT * FROM table" - result = mysql_loader.load_data(query) - - assert "doc_id" in result - assert "data" in result - assert len(result["data"]) == 2 - assert result["data"][0]["meta_data"]["url"] == query - assert result["data"][1]["meta_data"]["url"] == query - - doc_id = hashlib.sha256((query + ", ".join([d["content"] for d in result["data"]])).encode()).hexdigest() - - assert result["doc_id"] == doc_id - assert mock_cursor.execute.called_with(query) - - -def test_mysql_loader_load_data_invalid_query(mysql_loader): - with pytest.raises(ValueError, match="Invalid mysql query: 123"): - mysql_loader.load_data(query=123) diff --git a/embedchain/tests/loaders/test_notion.py b/embedchain/tests/loaders/test_notion.py deleted file mode 100644 index c9849c36f..000000000 --- a/embedchain/tests/loaders/test_notion.py +++ /dev/null @@ -1,36 +0,0 @@ -import hashlib -import os -from unittest.mock import Mock, patch - -import pytest - -from embedchain.loaders.notion import NotionLoader - - -@pytest.fixture -def notion_loader(): - with patch.dict(os.environ, {"NOTION_INTEGRATION_TOKEN": "test_notion_token"}): - yield NotionLoader() - - -def test_load_data(notion_loader): - source = "https://www.notion.so/Test-Page-1234567890abcdef1234567890abcdef" - mock_text = "This is a test page." - expected_doc_id = hashlib.sha256((mock_text + source).encode()).hexdigest() - expected_data = [ - { - "content": mock_text, - "meta_data": {"url": "notion-12345678-90ab-cdef-1234-567890abcdef"}, # formatted_id - } - ] - - mock_page = Mock() - mock_page.text = mock_text - mock_documents = [mock_page] - - with patch("embedchain.loaders.notion.NotionPageLoader") as mock_reader: - mock_reader.return_value.load_data.return_value = mock_documents - result = notion_loader.load_data(source) - - assert result["doc_id"] == expected_doc_id - assert result["data"] == expected_data diff --git a/embedchain/tests/loaders/test_openapi.py b/embedchain/tests/loaders/test_openapi.py deleted file mode 100644 index b39462c23..000000000 --- a/embedchain/tests/loaders/test_openapi.py +++ /dev/null @@ -1,26 +0,0 @@ -import pytest - -from embedchain.loaders.openapi import OpenAPILoader - - -@pytest.fixture -def openapi_loader(): - return OpenAPILoader() - - -def test_load_data(openapi_loader, mocker): - mocker.patch("builtins.open", mocker.mock_open(read_data="key1: value1\nkey2: value2")) - - mocker.patch("hashlib.sha256", return_value=mocker.Mock(hexdigest=lambda: "mock_hash")) - - file_path = "configs/openai_openapi.yaml" - result = openapi_loader.load_data(file_path) - - expected_doc_id = "mock_hash" - expected_data = [ - {"content": "key1: value1", "meta_data": {"url": file_path, "row": 1}}, - {"content": "key2: value2", "meta_data": {"url": file_path, "row": 2}}, - ] - - assert result["doc_id"] == expected_doc_id - assert result["data"] == expected_data diff --git a/embedchain/tests/loaders/test_pdf_file.py b/embedchain/tests/loaders/test_pdf_file.py deleted file mode 100644 index 6e6dda6e5..000000000 --- a/embedchain/tests/loaders/test_pdf_file.py +++ /dev/null @@ -1,36 +0,0 @@ -import pytest -from langchain.schema import Document - - -def test_load_data(loader, mocker): - mocked_pypdfloader = mocker.patch("embedchain.loaders.pdf_file.PyPDFLoader") - mocked_pypdfloader.return_value.load_and_split.return_value = [ - Document(page_content="Page 0 Content", metadata={"source": "example.pdf", "page": 0}), - Document(page_content="Page 1 Content", metadata={"source": "example.pdf", "page": 1}), - ] - - mock_sha256 = mocker.patch("embedchain.loaders.docs_site_loader.hashlib.sha256") - doc_id = "mocked_hash" - mock_sha256.return_value.hexdigest.return_value = doc_id - - result = loader.load_data("dummy_url") - assert result["doc_id"] is doc_id - assert result["data"] == [ - {"content": "Page 0 Content", "meta_data": {"source": "example.pdf", "page": 0, "url": "dummy_url"}}, - {"content": "Page 1 Content", "meta_data": {"source": "example.pdf", "page": 1, "url": "dummy_url"}}, - ] - - -def test_load_data_fails_to_find_data(loader, mocker): - mocked_pypdfloader = mocker.patch("embedchain.loaders.pdf_file.PyPDFLoader") - mocked_pypdfloader.return_value.load_and_split.return_value = [] - - with pytest.raises(ValueError): - loader.load_data("dummy_url") - - -@pytest.fixture -def loader(): - from embedchain.loaders.pdf_file import PdfFileLoader - - return PdfFileLoader() diff --git a/embedchain/tests/loaders/test_postgres.py b/embedchain/tests/loaders/test_postgres.py deleted file mode 100644 index 72a7d2a7f..000000000 --- a/embedchain/tests/loaders/test_postgres.py +++ /dev/null @@ -1,60 +0,0 @@ -from unittest.mock import MagicMock - -import psycopg -import pytest - -from embedchain.loaders.postgres import PostgresLoader - - -@pytest.fixture -def postgres_loader(mocker): - with mocker.patch.object(psycopg, "connect"): - config = {"url": "postgres://user:password@localhost:5432/database"} - loader = PostgresLoader(config=config) - yield loader - - -def test_postgres_loader_initialization(postgres_loader): - assert postgres_loader.connection is not None - assert postgres_loader.cursor is not None - - -def test_postgres_loader_invalid_config(): - with pytest.raises(ValueError, match="Must provide the valid config. Received: None"): - PostgresLoader(config=None) - - -def test_load_data(postgres_loader, monkeypatch): - mock_cursor = MagicMock() - monkeypatch.setattr(postgres_loader, "cursor", mock_cursor) - - query = "SELECT * FROM table" - mock_cursor.fetchall.return_value = [(1, "data1"), (2, "data2")] - - result = postgres_loader.load_data(query) - - assert "doc_id" in result - assert "data" in result - assert len(result["data"]) == 2 - assert result["data"][0]["meta_data"]["url"] == query - assert result["data"][1]["meta_data"]["url"] == query - assert mock_cursor.execute.called_with(query) - - -def test_load_data_exception(postgres_loader, monkeypatch): - mock_cursor = MagicMock() - monkeypatch.setattr(postgres_loader, "cursor", mock_cursor) - - _ = "SELECT * FROM table" - mock_cursor.execute.side_effect = Exception("Mocked exception") - - with pytest.raises( - ValueError, match=r"Failed to load data using query=SELECT \* FROM table with: Mocked exception" - ): - postgres_loader.load_data("SELECT * FROM table") - - -def test_close_connection(postgres_loader): - postgres_loader.close_connection() - assert postgres_loader.cursor is None - assert postgres_loader.connection is None diff --git a/embedchain/tests/loaders/test_slack.py b/embedchain/tests/loaders/test_slack.py deleted file mode 100644 index 8a2831f0e..000000000 --- a/embedchain/tests/loaders/test_slack.py +++ /dev/null @@ -1,47 +0,0 @@ -import pytest - -from embedchain.loaders.slack import SlackLoader - - -@pytest.fixture -def slack_loader(mocker, monkeypatch): - # Mocking necessary dependencies - mocker.patch("slack_sdk.WebClient") - mocker.patch("ssl.create_default_context") - mocker.patch("certifi.where") - - monkeypatch.setenv("SLACK_USER_TOKEN", "slack_user_token") - - return SlackLoader() - - -def test_slack_loader_initialization(slack_loader): - assert slack_loader.client is not None - assert slack_loader.config == {"base_url": "https://www.slack.com/api/"} - - -def test_slack_loader_setup_loader(slack_loader): - slack_loader._setup_loader({"base_url": "https://custom.slack.api/"}) - - assert slack_loader.client is not None - - -def test_slack_loader_check_query(slack_loader): - valid_json_query = "test_query" - invalid_query = 123 - - slack_loader._check_query(valid_json_query) - - with pytest.raises(ValueError): - slack_loader._check_query(invalid_query) - - -def test_slack_loader_load_data(slack_loader, mocker): - valid_json_query = "in:random" - - mocker.patch.object(slack_loader.client, "search_messages", return_value={"messages": {}}) - - result = slack_loader.load_data(valid_json_query) - - assert "doc_id" in result - assert "data" in result diff --git a/embedchain/tests/loaders/test_web_page.py b/embedchain/tests/loaders/test_web_page.py deleted file mode 100644 index 46036ee20..000000000 --- a/embedchain/tests/loaders/test_web_page.py +++ /dev/null @@ -1,148 +0,0 @@ -import hashlib -from unittest.mock import Mock, patch - -import pytest -import requests - -from embedchain.loaders.web_page import WebPageLoader - - -@pytest.fixture -def web_page_loader(): - return WebPageLoader() - - -def test_load_data(web_page_loader): - page_url = "https://example.com/page" - mock_response = Mock() - mock_response.status_code = 200 - mock_response.content = """ - - - Test Page - - -
    -

    This is some test content.

    -
    - - - """ - with patch("embedchain.loaders.web_page.WebPageLoader._session.get", return_value=mock_response): - result = web_page_loader.load_data(page_url) - - content = web_page_loader._get_clean_content(mock_response.content, page_url) - expected_doc_id = hashlib.sha256((content + page_url).encode()).hexdigest() - assert result["doc_id"] == expected_doc_id - - expected_data = [ - { - "content": content, - "meta_data": { - "url": page_url, - }, - } - ] - - assert result["data"] == expected_data - - -def test_get_clean_content_excludes_unnecessary_info(web_page_loader): - mock_html = """ - - - Sample HTML - - - - - - -
    Form Content
    -
    Main Content
    -
    Footer Content
    - - - SVG Content - Canvas Content - - - - - -
    Header Sidebar Wrapper Content
    -
    Blog Sidebar Wrapper Content
    - - - - """ - - tags_to_exclude = [ - "nav", - "aside", - "form", - "header", - "noscript", - "svg", - "canvas", - "footer", - "script", - "style", - ] - ids_to_exclude = ["sidebar", "main-navigation", "menu-main-menu"] - classes_to_exclude = [ - "elementor-location-header", - "navbar-header", - "nav", - "header-sidebar-wrapper", - "blog-sidebar-wrapper", - "related-posts", - ] - - content = web_page_loader._get_clean_content(mock_html, "https://example.com/page") - - for tag in tags_to_exclude: - assert tag not in content - - for id in ids_to_exclude: - assert id not in content - - for class_name in classes_to_exclude: - assert class_name not in content - - assert len(content) > 0 - - -def test_fetch_reference_links_success(web_page_loader): - # Mock a successful response - response = Mock(spec=requests.Response) - response.status_code = 200 - response.content = b""" - - - Example - Another Example - Relative Link - - - """ - - expected_links = ["http://example.com", "https://another-example.com"] - result = web_page_loader.fetch_reference_links(response) - assert result == expected_links - - -def test_fetch_reference_links_failure(web_page_loader): - # Mock a failed response - response = Mock(spec=requests.Response) - response.status_code = 404 - response.content = b"" - - expected_links = [] - result = web_page_loader.fetch_reference_links(response) - assert result == expected_links diff --git a/embedchain/tests/loaders/test_xml.py b/embedchain/tests/loaders/test_xml.py deleted file mode 100644 index d1ff5daad..000000000 --- a/embedchain/tests/loaders/test_xml.py +++ /dev/null @@ -1,62 +0,0 @@ -import tempfile - -import pytest - -from embedchain.loaders.xml import XmlLoader - -# Taken from https://github.com/langchain-ai/langchain/blob/master/libs/langchain/tests/integration_tests/examples/factbook.xml -SAMPLE_XML = """ - - - United States - Washington, DC - Joe Biden - Baseball - - - Canada - Ottawa - Justin Trudeau - Hockey - - - France - Paris - Emmanuel Macron - Soccer - - - Trinidad & Tobado - Port of Spain - Keith Rowley - Track & Field - -""" - - -@pytest.mark.parametrize("xml", [SAMPLE_XML]) -def test_load_data(xml: str): - """ - Test XML loader - - Tests that XML file is loaded, metadata is correct and content is correct - """ - # Creating temporary XML file - with tempfile.NamedTemporaryFile(mode="w+") as tmpfile: - tmpfile.write(xml) - - tmpfile.seek(0) - filename = tmpfile.name - - # Loading CSV using XmlLoader - loader = XmlLoader() - result = loader.load_data(filename) - data = result["data"] - - # Assertions - assert len(data) == 1 - assert "United States Washington, DC Joe Biden" in data[0]["content"] - assert "Canada Ottawa Justin Trudeau" in data[0]["content"] - assert "France Paris Emmanuel Macron" in data[0]["content"] - assert "Trinidad & Tobado Port of Spain Keith Rowley" in data[0]["content"] - assert data[0]["meta_data"]["url"] == filename diff --git a/embedchain/tests/loaders/test_youtube_video.py b/embedchain/tests/loaders/test_youtube_video.py deleted file mode 100644 index b8184a6e5..000000000 --- a/embedchain/tests/loaders/test_youtube_video.py +++ /dev/null @@ -1,53 +0,0 @@ -import hashlib -from unittest.mock import MagicMock, Mock, patch - -import pytest - -from embedchain.loaders.youtube_video import YoutubeVideoLoader - - -@pytest.fixture -def youtube_video_loader(): - return YoutubeVideoLoader() - - -def test_load_data(youtube_video_loader): - video_url = "https://www.youtube.com/watch?v=VIDEO_ID" - mock_loader = Mock() - mock_page_content = "This is a YouTube video content." - mock_loader.load.return_value = [ - MagicMock( - page_content=mock_page_content, - metadata={"url": video_url, "title": "Test Video"}, - ) - ] - - mock_transcript = [{"text": "sample text", "start": 0.0, "duration": 5.0}] - - with patch("embedchain.loaders.youtube_video.YoutubeLoader.from_youtube_url", return_value=mock_loader), patch( - "embedchain.loaders.youtube_video.YouTubeTranscriptApi.get_transcript", return_value=mock_transcript - ): - result = youtube_video_loader.load_data(video_url) - - expected_doc_id = hashlib.sha256((mock_page_content + video_url).encode()).hexdigest() - - assert result["doc_id"] == expected_doc_id - - expected_data = [ - { - "content": "This is a YouTube video content.", - "meta_data": {"url": video_url, "title": "Test Video", "transcript": "Unavailable"}, - } - ] - - assert result["data"] == expected_data - - -def test_load_data_with_empty_doc(youtube_video_loader): - video_url = "https://www.youtube.com/watch?v=VIDEO_ID" - mock_loader = Mock() - mock_loader.load.return_value = [] - - with patch("embedchain.loaders.youtube_video.YoutubeLoader.from_youtube_url", return_value=mock_loader): - with pytest.raises(ValueError): - youtube_video_loader.load_data(video_url) diff --git a/embedchain/tests/memory/test_chat_memory.py b/embedchain/tests/memory/test_chat_memory.py deleted file mode 100644 index 6fac2a643..000000000 --- a/embedchain/tests/memory/test_chat_memory.py +++ /dev/null @@ -1,91 +0,0 @@ -import pytest - -from embedchain.memory.base import ChatHistory -from embedchain.memory.message import ChatMessage - - -# Fixture for creating an instance of ChatHistory -@pytest.fixture -def chat_memory_instance(): - return ChatHistory() - - -def test_add_chat_memory(chat_memory_instance): - app_id = "test_app" - session_id = "test_session" - human_message = "Hello, how are you?" - ai_message = "I'm fine, thank you!" - - chat_message = ChatMessage() - chat_message.add_user_message(human_message) - chat_message.add_ai_message(ai_message) - - chat_memory_instance.add(app_id, session_id, chat_message) - - assert chat_memory_instance.count(app_id, session_id) == 1 - chat_memory_instance.delete(app_id, session_id) - - -def test_get(chat_memory_instance): - app_id = "test_app" - session_id = "test_session" - - for i in range(1, 7): - human_message = f"Question {i}" - ai_message = f"Answer {i}" - - chat_message = ChatMessage() - chat_message.add_user_message(human_message) - chat_message.add_ai_message(ai_message) - - chat_memory_instance.add(app_id, session_id, chat_message) - - recent_memories = chat_memory_instance.get(app_id, session_id, num_rounds=5) - - assert len(recent_memories) == 5 - - all_memories = chat_memory_instance.get(app_id, fetch_all=True) - - assert len(all_memories) == 6 - - -def test_delete_chat_history(chat_memory_instance): - app_id = "test_app" - session_id = "test_session" - - for i in range(1, 6): - human_message = f"Question {i}" - ai_message = f"Answer {i}" - - chat_message = ChatMessage() - chat_message.add_user_message(human_message) - chat_message.add_ai_message(ai_message) - - chat_memory_instance.add(app_id, session_id, chat_message) - - session_id_2 = "test_session_2" - - for i in range(1, 6): - human_message = f"Question {i}" - ai_message = f"Answer {i}" - - chat_message = ChatMessage() - chat_message.add_user_message(human_message) - chat_message.add_ai_message(ai_message) - - chat_memory_instance.add(app_id, session_id_2, chat_message) - - chat_memory_instance.delete(app_id, session_id) - - assert chat_memory_instance.count(app_id, session_id) == 0 - assert chat_memory_instance.count(app_id) == 5 - - chat_memory_instance.delete(app_id) - - assert chat_memory_instance.count(app_id) == 0 - - -@pytest.fixture -def close_connection(chat_memory_instance): - yield - chat_memory_instance.close_connection() diff --git a/embedchain/tests/memory/test_memory_messages.py b/embedchain/tests/memory/test_memory_messages.py deleted file mode 100644 index 23f7b53b9..000000000 --- a/embedchain/tests/memory/test_memory_messages.py +++ /dev/null @@ -1,37 +0,0 @@ -from embedchain.memory.message import BaseMessage, ChatMessage - - -def test_ec_base_message(): - content = "Hello, how are you?" - created_by = "human" - metadata = {"key": "value"} - - message = BaseMessage(content=content, created_by=created_by, metadata=metadata) - - assert message.content == content - assert message.created_by == created_by - assert message.metadata == metadata - assert message.type is None - assert message.is_lc_serializable() is True - assert str(message) == f"{created_by}: {content}" - - -def test_ec_base_chat_message(): - human_message_content = "Hello, how are you?" - ai_message_content = "I'm fine, thank you!" - human_metadata = {"user": "John"} - ai_metadata = {"response_time": 0.5} - - chat_message = ChatMessage() - chat_message.add_user_message(human_message_content, metadata=human_metadata) - chat_message.add_ai_message(ai_message_content, metadata=ai_metadata) - - assert chat_message.human_message.content == human_message_content - assert chat_message.human_message.created_by == "human" - assert chat_message.human_message.metadata == human_metadata - - assert chat_message.ai_message.content == ai_message_content - assert chat_message.ai_message.created_by == "ai" - assert chat_message.ai_message.metadata == ai_metadata - - assert str(chat_message) == f"human: {human_message_content}\nai: {ai_message_content}" diff --git a/embedchain/tests/models/test_data_type.py b/embedchain/tests/models/test_data_type.py deleted file mode 100644 index 60d66282c..000000000 --- a/embedchain/tests/models/test_data_type.py +++ /dev/null @@ -1,34 +0,0 @@ -from embedchain.models.data_type import ( - DataType, - DirectDataType, - IndirectDataType, - SpecialDataType, -) - - -def test_subclass_types_in_data_type(): - """Test that all data type category subclasses are contained in the composite data type""" - # Check if DirectDataType values are in DataType - for data_type in DirectDataType: - assert data_type.value in DataType._value2member_map_ - - # Check if IndirectDataType values are in DataType - for data_type in IndirectDataType: - assert data_type.value in DataType._value2member_map_ - - # Check if SpecialDataType values are in DataType - for data_type in SpecialDataType: - assert data_type.value in DataType._value2member_map_ - - -def test_data_type_in_subclasses(): - """Test that all data types in the composite data type are categorized in a subclass""" - for data_type in DataType: - if data_type.value in DirectDataType._value2member_map_: - assert data_type.value in DirectDataType._value2member_map_ - elif data_type.value in IndirectDataType._value2member_map_: - assert data_type.value in IndirectDataType._value2member_map_ - elif data_type.value in SpecialDataType._value2member_map_: - assert data_type.value in SpecialDataType._value2member_map_ - else: - assert False, f"{data_type.value} not found in any subclass enums" diff --git a/embedchain/tests/telemetry/test_posthog.py b/embedchain/tests/telemetry/test_posthog.py deleted file mode 100644 index 8efd150ea..000000000 --- a/embedchain/tests/telemetry/test_posthog.py +++ /dev/null @@ -1,65 +0,0 @@ -import logging -import os - -from embedchain.telemetry.posthog import AnonymousTelemetry - - -class TestAnonymousTelemetry: - def test_init(self, mocker): - # Enable telemetry specifically for this test - os.environ["EC_TELEMETRY"] = "true" - mock_posthog = mocker.patch("embedchain.telemetry.posthog.Posthog") - telemetry = AnonymousTelemetry() - assert telemetry.project_api_key == "phc_PHQDA5KwztijnSojsxJ2c1DuJd52QCzJzT2xnSGvjN2" - assert telemetry.host == "https://app.posthog.com" - assert telemetry.enabled is True - assert telemetry.user_id - mock_posthog.assert_called_once_with(project_api_key=telemetry.project_api_key, host=telemetry.host) - - def test_init_with_disabled_telemetry(self, mocker): - mocker.patch("embedchain.telemetry.posthog.Posthog") - telemetry = AnonymousTelemetry() - assert telemetry.enabled is False - assert telemetry.posthog.disabled is True - - def test_get_user_id(self, mocker, tmpdir): - mock_uuid = mocker.patch("embedchain.telemetry.posthog.uuid.uuid4") - mock_uuid.return_value = "unique_user_id" - config_file = tmpdir.join("config.json") - mocker.patch("embedchain.telemetry.posthog.CONFIG_FILE", str(config_file)) - telemetry = AnonymousTelemetry() - - user_id = telemetry._get_user_id() - assert user_id == "unique_user_id" - assert config_file.read() == '{"user_id": "unique_user_id"}' - - def test_capture(self, mocker): - # Enable telemetry specifically for this test - os.environ["EC_TELEMETRY"] = "true" - mock_posthog = mocker.patch("embedchain.telemetry.posthog.Posthog") - telemetry = AnonymousTelemetry() - event_name = "test_event" - properties = {"key": "value"} - telemetry.capture(event_name, properties) - - mock_posthog.assert_called_once_with( - project_api_key=telemetry.project_api_key, - host=telemetry.host, - ) - mock_posthog.return_value.capture.assert_called_once_with( - telemetry.user_id, - event_name, - properties, - ) - - def test_capture_with_exception(self, mocker, caplog): - os.environ["EC_TELEMETRY"] = "true" - mock_posthog = mocker.patch("embedchain.telemetry.posthog.Posthog") - mock_posthog.return_value.capture.side_effect = Exception("Test Exception") - telemetry = AnonymousTelemetry() - event_name = "test_event" - properties = {"key": "value"} - with caplog.at_level(logging.ERROR): - telemetry.capture(event_name, properties) - assert "Failed to send telemetry event" in caplog.text - caplog.clear() diff --git a/embedchain/tests/test_app.py b/embedchain/tests/test_app.py deleted file mode 100644 index 370503d7e..000000000 --- a/embedchain/tests/test_app.py +++ /dev/null @@ -1,111 +0,0 @@ -import os - -import pytest -import yaml - -from embedchain import App -from embedchain.config import ChromaDbConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.llm.base import BaseLlm -from embedchain.vectordb.base import BaseVectorDB -from embedchain.vectordb.chroma import ChromaDB - - -@pytest.fixture -def app(): - os.environ["OPENAI_API_KEY"] = "test-api-key" - os.environ["OPENAI_API_BASE"] = "test-api-base" - return App() - - -def test_app(app): - assert isinstance(app.llm, BaseLlm) - assert isinstance(app.db, BaseVectorDB) - assert isinstance(app.embedding_model, BaseEmbedder) - - -class TestConfigForAppComponents: - def test_constructor_config(self): - collection_name = "my-test-collection" - db = ChromaDB(config=ChromaDbConfig(collection_name=collection_name)) - app = App(db=db) - assert app.db.config.collection_name == collection_name - - def test_component_config(self): - collection_name = "my-test-collection" - database = ChromaDB(config=ChromaDbConfig(collection_name=collection_name)) - app = App(db=database) - assert app.db.config.collection_name == collection_name - - -class TestAppFromConfig: - def load_config_data(self, yaml_path): - with open(yaml_path, "r") as file: - return yaml.safe_load(file) - - def test_from_chroma_config(self, mocker): - mocker.patch("embedchain.vectordb.chroma.chromadb.Client") - - yaml_path = "configs/chroma.yaml" - config_data = self.load_config_data(yaml_path) - - app = App.from_config(config_path=yaml_path) - - # Check if the App instance and its components were created correctly - assert isinstance(app, App) - - # Validate the AppConfig values - assert app.config.id == config_data["app"]["config"]["id"] - # Even though not present in the config, the default value is used - assert app.config.collect_metrics is True - - # Validate the LLM config values - llm_config = config_data["llm"]["config"] - assert app.llm.config.temperature == llm_config["temperature"] - assert app.llm.config.max_tokens == llm_config["max_tokens"] - assert app.llm.config.top_p == llm_config["top_p"] - assert app.llm.config.stream == llm_config["stream"] - - # Validate the VectorDB config values - db_config = config_data["vectordb"]["config"] - assert app.db.config.collection_name == db_config["collection_name"] - assert app.db.config.dir == db_config["dir"] - assert app.db.config.allow_reset == db_config["allow_reset"] - - # Validate the Embedder config values - embedder_config = config_data["embedder"]["config"] - assert app.embedding_model.config.model == embedder_config["model"] - assert app.embedding_model.config.deployment_name == embedder_config.get("deployment_name") - - def test_from_opensource_config(self, mocker): - mocker.patch("embedchain.vectordb.chroma.chromadb.Client") - - yaml_path = "configs/opensource.yaml" - config_data = self.load_config_data(yaml_path) - - app = App.from_config(yaml_path) - - # Check if the App instance and its components were created correctly - assert isinstance(app, App) - - # Validate the AppConfig values - assert app.config.id == config_data["app"]["config"]["id"] - assert app.config.collect_metrics == config_data["app"]["config"]["collect_metrics"] - - # Validate the LLM config values - llm_config = config_data["llm"]["config"] - assert app.llm.config.model == llm_config["model"] - assert app.llm.config.temperature == llm_config["temperature"] - assert app.llm.config.max_tokens == llm_config["max_tokens"] - assert app.llm.config.top_p == llm_config["top_p"] - assert app.llm.config.stream == llm_config["stream"] - - # Validate the VectorDB config values - db_config = config_data["vectordb"]["config"] - assert app.db.config.collection_name == db_config["collection_name"] - assert app.db.config.dir == db_config["dir"] - assert app.db.config.allow_reset == db_config["allow_reset"] - - # Validate the Embedder config values - embedder_config = config_data["embedder"]["config"] - assert app.embedding_model.config.deployment_name == embedder_config["deployment_name"] diff --git a/embedchain/tests/test_client.py b/embedchain/tests/test_client.py deleted file mode 100644 index 5259ecd69..000000000 --- a/embedchain/tests/test_client.py +++ /dev/null @@ -1,53 +0,0 @@ -import pytest - -from embedchain import Client - - -class TestClient: - @pytest.fixture - def mock_requests_post(self, mocker): - return mocker.patch("embedchain.client.requests.post") - - def test_valid_api_key(self, mock_requests_post): - mock_requests_post.return_value.status_code = 200 - client = Client(api_key="valid_api_key") - assert client.check("valid_api_key") is True - - def test_invalid_api_key(self, mock_requests_post): - mock_requests_post.return_value.status_code = 401 - with pytest.raises(ValueError): - Client(api_key="invalid_api_key") - - def test_update_valid_api_key(self, mock_requests_post): - mock_requests_post.return_value.status_code = 200 - client = Client(api_key="valid_api_key") - client.update("new_valid_api_key") - assert client.get() == "new_valid_api_key" - - def test_clear_api_key(self, mock_requests_post): - mock_requests_post.return_value.status_code = 200 - client = Client(api_key="valid_api_key") - client.clear() - assert client.get() is None - - def test_save_api_key(self, mock_requests_post): - mock_requests_post.return_value.status_code = 200 - api_key_to_save = "valid_api_key" - client = Client(api_key=api_key_to_save) - client.save() - assert client.get() == api_key_to_save - - def test_load_api_key_from_config(self, mocker): - mocker.patch("embedchain.Client.load_config", return_value={"api_key": "test_api_key"}) - client = Client() - assert client.get() == "test_api_key" - - def test_load_invalid_api_key_from_config(self, mocker): - mocker.patch("embedchain.Client.load_config", return_value={}) - with pytest.raises(ValueError): - Client() - - def test_load_missing_api_key_from_config(self, mocker): - mocker.patch("embedchain.Client.load_config", return_value={}) - with pytest.raises(ValueError): - Client() diff --git a/embedchain/tests/test_factory.py b/embedchain/tests/test_factory.py deleted file mode 100644 index c6e1ea0e5..000000000 --- a/embedchain/tests/test_factory.py +++ /dev/null @@ -1,66 +0,0 @@ -import os - -import pytest - -import embedchain -import embedchain.embedder.gpt4all -import embedchain.embedder.huggingface -import embedchain.embedder.openai -import embedchain.embedder.vertexai -import embedchain.llm.anthropic -import embedchain.llm.openai -import embedchain.vectordb.chroma -import embedchain.vectordb.elasticsearch -import embedchain.vectordb.opensearch -from embedchain.factory import EmbedderFactory, LlmFactory, VectorDBFactory - - -class TestFactories: - @pytest.mark.parametrize( - "provider_name, config_data, expected_class", - [ - ("openai", {}, embedchain.llm.openai.OpenAILlm), - ("anthropic", {}, embedchain.llm.anthropic.AnthropicLlm), - ], - ) - def test_llm_factory_create(self, provider_name, config_data, expected_class): - os.environ["ANTHROPIC_API_KEY"] = "test_api_key" - os.environ["OPENAI_API_KEY"] = "test_api_key" - os.environ["OPENAI_API_BASE"] = "test_api_base" - llm_instance = LlmFactory.create(provider_name, config_data) - assert isinstance(llm_instance, expected_class) - - @pytest.mark.parametrize( - "provider_name, config_data, expected_class", - [ - ("gpt4all", {}, embedchain.embedder.gpt4all.GPT4AllEmbedder), - ( - "huggingface", - {"model": "sentence-transformers/all-mpnet-base-v2", "vector_dimension": 768}, - embedchain.embedder.huggingface.HuggingFaceEmbedder, - ), - ("vertexai", {"model": "textembedding-gecko"}, embedchain.embedder.vertexai.VertexAIEmbedder), - ("openai", {}, embedchain.embedder.openai.OpenAIEmbedder), - ], - ) - def test_embedder_factory_create(self, mocker, provider_name, config_data, expected_class): - mocker.patch("embedchain.embedder.vertexai.VertexAIEmbedder", autospec=True) - embedder_instance = EmbedderFactory.create(provider_name, config_data) - assert isinstance(embedder_instance, expected_class) - - @pytest.mark.parametrize( - "provider_name, config_data, expected_class", - [ - ("chroma", {}, embedchain.vectordb.chroma.ChromaDB), - ( - "opensearch", - {"opensearch_url": "http://localhost:9200", "http_auth": ("admin", "admin")}, - embedchain.vectordb.opensearch.OpenSearchDB, - ), - ("elasticsearch", {"es_url": "http://localhost:9200"}, embedchain.vectordb.elasticsearch.ElasticsearchDB), - ], - ) - def test_vectordb_factory_create(self, mocker, provider_name, config_data, expected_class): - mocker.patch("embedchain.vectordb.opensearch.OpenSearchDB", autospec=True) - vectordb_instance = VectorDBFactory.create(provider_name, config_data) - assert isinstance(vectordb_instance, expected_class) diff --git a/embedchain/tests/test_utils.py b/embedchain/tests/test_utils.py deleted file mode 100644 index 3e50e1e16..000000000 --- a/embedchain/tests/test_utils.py +++ /dev/null @@ -1,38 +0,0 @@ -import yaml - -from embedchain.utils.misc import validate_config - -CONFIG_YAMLS = [ - "configs/anthropic.yaml", - "configs/azure_openai.yaml", - "configs/chroma.yaml", - "configs/chunker.yaml", - "configs/cohere.yaml", - "configs/together.yaml", - "configs/ollama.yaml", - "configs/full-stack.yaml", - "configs/gpt4.yaml", - "configs/gpt4all.yaml", - "configs/huggingface.yaml", - "configs/jina.yaml", - "configs/llama2.yaml", - "configs/opensearch.yaml", - "configs/opensource.yaml", - "configs/pinecone.yaml", - "configs/vertexai.yaml", - "configs/weaviate.yaml", -] - - -def test_all_config_yamls(): - """Test that all config yamls are valid.""" - for config_yaml in CONFIG_YAMLS: - with open(config_yaml, "r") as f: - config = yaml.safe_load(f) - assert config is not None - - try: - validate_config(config) - except Exception as e: - print(f"Error in {config_yaml}: {e}") - raise e diff --git a/embedchain/tests/vectordb/test_chroma_db.py b/embedchain/tests/vectordb/test_chroma_db.py deleted file mode 100644 index 1e2659e3e..000000000 --- a/embedchain/tests/vectordb/test_chroma_db.py +++ /dev/null @@ -1,253 +0,0 @@ -import os -import shutil -from unittest.mock import patch - -import pytest -from chromadb.config import Settings - -from embedchain import App -from embedchain.config import AppConfig, ChromaDbConfig -from embedchain.vectordb.chroma import ChromaDB - -os.environ["OPENAI_API_KEY"] = "test-api-key" - - -@pytest.fixture -def chroma_db(): - return ChromaDB(config=ChromaDbConfig(host="test-host", port="1234")) - - -@pytest.fixture -def app_with_settings(): - chroma_config = ChromaDbConfig(allow_reset=True, dir="test-db") - chroma_db = ChromaDB(config=chroma_config) - app_config = AppConfig(collect_metrics=False) - return App(config=app_config, db=chroma_db) - - -@pytest.fixture(scope="session", autouse=True) -def cleanup_db(): - yield - try: - shutil.rmtree("test-db") - except OSError as e: - print("Error: %s - %s." % (e.filename, e.strerror)) - - -@patch("embedchain.vectordb.chroma.chromadb.Client") -def test_chroma_db_init_with_host_and_port(mock_client): - chroma_db = ChromaDB(config=ChromaDbConfig(host="test-host", port="1234")) # noqa - called_settings: Settings = mock_client.call_args[0][0] - assert called_settings.chroma_server_host == "test-host" - assert called_settings.chroma_server_http_port == "1234" - - -@patch("embedchain.vectordb.chroma.chromadb.Client") -def test_chroma_db_init_with_basic_auth(mock_client): - chroma_config = { - "host": "test-host", - "port": "1234", - "chroma_settings": { - "chroma_client_auth_provider": "chromadb.auth.basic.BasicAuthClientProvider", - "chroma_client_auth_credentials": "admin:admin", - }, - } - - ChromaDB(config=ChromaDbConfig(**chroma_config)) - called_settings: Settings = mock_client.call_args[0][0] - assert called_settings.chroma_server_host == "test-host" - assert called_settings.chroma_server_http_port == "1234" - assert ( - called_settings.chroma_client_auth_provider == chroma_config["chroma_settings"]["chroma_client_auth_provider"] - ) - assert ( - called_settings.chroma_client_auth_credentials - == chroma_config["chroma_settings"]["chroma_client_auth_credentials"] - ) - - -@patch("embedchain.vectordb.chroma.chromadb.Client") -def test_app_init_with_host_and_port(mock_client): - host = "test-host" - port = "1234" - config = AppConfig(collect_metrics=False) - db_config = ChromaDbConfig(host=host, port=port) - db = ChromaDB(config=db_config) - _app = App(config=config, db=db) - - called_settings: Settings = mock_client.call_args[0][0] - assert called_settings.chroma_server_host == host - assert called_settings.chroma_server_http_port == port - - -@patch("embedchain.vectordb.chroma.chromadb.Client") -def test_app_init_with_host_and_port_none(mock_client): - db = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - _app = App(config=AppConfig(collect_metrics=False), db=db) - - called_settings: Settings = mock_client.call_args[0][0] - assert called_settings.chroma_server_host is None - assert called_settings.chroma_server_http_port is None - - -def test_chroma_db_duplicates_throw_warning(caplog): - db = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.db.collection.add(embeddings=[[0, 0, 0]], ids=["0"]) - app.db.collection.add(embeddings=[[0, 0, 0]], ids=["0"]) - assert "Insert of existing embedding ID: 0" in caplog.text - assert "Add of existing embedding ID: 0" in caplog.text - app.db.reset() - - -def test_chroma_db_duplicates_collections_no_warning(caplog): - db = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.set_collection_name("test_collection_1") - app.db.collection.add(embeddings=[[0, 0, 0]], ids=["0"]) - app.set_collection_name("test_collection_2") - app.db.collection.add(embeddings=[[0, 0, 0]], ids=["0"]) - assert "Insert of existing embedding ID: 0" not in caplog.text - assert "Add of existing embedding ID: 0" not in caplog.text - app.db.reset() - app.set_collection_name("test_collection_1") - app.db.reset() - - -def test_chroma_db_collection_init_with_default_collection(): - db = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - assert app.db.collection.name == "embedchain_store" - - -def test_chroma_db_collection_init_with_custom_collection(): - db = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.set_collection_name(name="test_collection") - assert app.db.collection.name == "test_collection" - - -def test_chroma_db_collection_set_collection_name(): - db = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.set_collection_name("test_collection") - assert app.db.collection.name == "test_collection" - - -def test_chroma_db_collection_changes_encapsulated(): - db = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.set_collection_name("test_collection_1") - assert app.db.count() == 0 - - app.db.collection.add(embeddings=[0, 0, 0], ids=["0"]) - assert app.db.count() == 1 - - app.set_collection_name("test_collection_2") - assert app.db.count() == 0 - - app.db.collection.add(embeddings=[0, 0, 0], ids=["0"]) - app.set_collection_name("test_collection_1") - assert app.db.count() == 1 - app.db.reset() - app.set_collection_name("test_collection_2") - app.db.reset() - - -def test_chroma_db_collection_collections_are_persistent(): - db = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.set_collection_name("test_collection_1") - app.db.collection.add(embeddings=[[0, 0, 0]], ids=["0"]) - del app - - db = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.set_collection_name("test_collection_1") - assert app.db.count() == 1 - - app.db.reset() - - -def test_chroma_db_collection_parallel_collections(): - db1 = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db", collection_name="test_collection_1")) - app1 = App( - config=AppConfig(collect_metrics=False), - db=db1, - ) - db2 = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db", collection_name="test_collection_2")) - app2 = App( - config=AppConfig(collect_metrics=False), - db=db2, - ) - - # cleanup if any previous tests failed or were interrupted - app1.db.reset() - app2.db.reset() - - app1.db.collection.add(embeddings=[0, 0, 0], ids=["0"]) - assert app1.db.count() == 1 - assert app2.db.count() == 0 - - app1.db.collection.add(embeddings=[[0, 0, 0], [1, 1, 1]], ids=["1", "2"]) - app2.db.collection.add(embeddings=[0, 0, 0], ids=["0"]) - - app1.set_collection_name("test_collection_2") - assert app1.db.count() == 1 - app2.set_collection_name("test_collection_1") - assert app2.db.count() == 3 - - # cleanup - app1.db.reset() - app2.db.reset() - - -def test_chroma_db_collection_ids_share_collections(): - db1 = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app1 = App(config=AppConfig(collect_metrics=False), db=db1) - app1.set_collection_name("one_collection") - db2 = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app2 = App(config=AppConfig(collect_metrics=False), db=db2) - app2.set_collection_name("one_collection") - - app1.db.collection.add(embeddings=[[0, 0, 0], [1, 1, 1]], ids=["0", "1"]) - app2.db.collection.add(embeddings=[0, 0, 0], ids=["2"]) - - assert app1.db.count() == 3 - assert app2.db.count() == 3 - - # cleanup - app1.db.reset() - app2.db.reset() - - -def test_chroma_db_collection_reset(): - db1 = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app1 = App(config=AppConfig(collect_metrics=False), db=db1) - app1.set_collection_name("one_collection") - db2 = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app2 = App(config=AppConfig(collect_metrics=False), db=db2) - app2.set_collection_name("two_collection") - db3 = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app3 = App(config=AppConfig(collect_metrics=False), db=db3) - app3.set_collection_name("three_collection") - db4 = ChromaDB(config=ChromaDbConfig(allow_reset=True, dir="test-db")) - app4 = App(config=AppConfig(collect_metrics=False), db=db4) - app4.set_collection_name("four_collection") - - app1.db.collection.add(embeddings=[0, 0, 0], ids=["1"]) - app2.db.collection.add(embeddings=[0, 0, 0], ids=["2"]) - app3.db.collection.add(embeddings=[0, 0, 0], ids=["3"]) - app4.db.collection.add(embeddings=[0, 0, 0], ids=["4"]) - - app1.db.reset() - - assert app1.db.count() == 0 - assert app2.db.count() == 1 - assert app3.db.count() == 1 - assert app4.db.count() == 1 - - # cleanup - app2.db.reset() - app3.db.reset() - app4.db.reset() diff --git a/embedchain/tests/vectordb/test_elasticsearch_db.py b/embedchain/tests/vectordb/test_elasticsearch_db.py deleted file mode 100644 index 2cb42c424..000000000 --- a/embedchain/tests/vectordb/test_elasticsearch_db.py +++ /dev/null @@ -1,86 +0,0 @@ -import os -import unittest -from unittest.mock import patch - -from embedchain import App -from embedchain.config import AppConfig, ElasticsearchDBConfig -from embedchain.embedder.gpt4all import GPT4AllEmbedder -from embedchain.vectordb.elasticsearch import ElasticsearchDB - - -class TestEsDB(unittest.TestCase): - @patch("embedchain.vectordb.elasticsearch.Elasticsearch") - def test_setUp(self, mock_client): - self.db = ElasticsearchDB(config=ElasticsearchDBConfig(es_url="https://localhost:9200")) - self.vector_dim = 384 - app_config = AppConfig(collect_metrics=False) - self.app = App(config=app_config, db=self.db) - - # Assert that the Elasticsearch client is stored in the ElasticsearchDB class. - self.assertEqual(self.db.client, mock_client.return_value) - - @patch("embedchain.vectordb.elasticsearch.Elasticsearch") - def test_query(self, mock_client): - self.db = ElasticsearchDB(config=ElasticsearchDBConfig(es_url="https://localhost:9200")) - app_config = AppConfig(collect_metrics=False) - self.app = App(config=app_config, db=self.db, embedding_model=GPT4AllEmbedder()) - - # Assert that the Elasticsearch client is stored in the ElasticsearchDB class. - self.assertEqual(self.db.client, mock_client.return_value) - - # Create some dummy data - documents = ["This is a document.", "This is another document."] - metadatas = [{"url": "url_1", "doc_id": "doc_id_1"}, {"url": "url_2", "doc_id": "doc_id_2"}] - ids = ["doc_1", "doc_2"] - - # Add the data to the database. - self.db.add(documents, metadatas, ids) - - search_response = { - "hits": { - "hits": [ - { - "_source": {"text": "This is a document.", "metadata": {"url": "url_1", "doc_id": "doc_id_1"}}, - "_score": 0.9, - }, - { - "_source": { - "text": "This is another document.", - "metadata": {"url": "url_2", "doc_id": "doc_id_2"}, - }, - "_score": 0.8, - }, - ] - } - } - - # Configure the mock client to return the mocked response. - mock_client.return_value.search.return_value = search_response - - # Query the database for the documents that are most similar to the query "This is a document". - query = "This is a document" - results_without_citations = self.db.query(query, n_results=2, where={}) - expected_results_without_citations = ["This is a document.", "This is another document."] - self.assertEqual(results_without_citations, expected_results_without_citations) - - results_with_citations = self.db.query(query, n_results=2, where={}, citations=True) - expected_results_with_citations = [ - ("This is a document.", {"url": "url_1", "doc_id": "doc_id_1", "score": 0.9}), - ("This is another document.", {"url": "url_2", "doc_id": "doc_id_2", "score": 0.8}), - ] - self.assertEqual(results_with_citations, expected_results_with_citations) - - def test_init_without_url(self): - # Make sure it's not loaded from env - try: - del os.environ["ELASTICSEARCH_URL"] - except KeyError: - pass - # Test if an exception is raised when an invalid es_config is provided - with self.assertRaises(AttributeError): - ElasticsearchDB() - - def test_init_with_invalid_es_config(self): - # Test if an exception is raised when an invalid es_config is provided - with self.assertRaises(TypeError): - ElasticsearchDB(es_config={"ES_URL": "some_url", "valid es_config": False}) diff --git a/embedchain/tests/vectordb/test_lancedb.py b/embedchain/tests/vectordb/test_lancedb.py deleted file mode 100644 index 91885bdd5..000000000 --- a/embedchain/tests/vectordb/test_lancedb.py +++ /dev/null @@ -1,215 +0,0 @@ -import os -import shutil - -import pytest - -from embedchain import App -from embedchain.config import AppConfig -from embedchain.config.vector_db.lancedb import LanceDBConfig -from embedchain.vectordb.lancedb import LanceDB - -os.environ["OPENAI_API_KEY"] = "test-api-key" - - -@pytest.fixture -def lancedb(): - return LanceDB(config=LanceDBConfig(dir="test-db", collection_name="test-coll")) - - -@pytest.fixture -def app_with_settings(): - lancedb_config = LanceDBConfig(allow_reset=True, dir="test-db-reset") - lancedb = LanceDB(config=lancedb_config) - app_config = AppConfig(collect_metrics=False) - return App(config=app_config, db=lancedb) - - -@pytest.fixture(scope="session", autouse=True) -def cleanup_db(): - yield - try: - shutil.rmtree("test-db.lance") - shutil.rmtree("test-db-reset.lance") - except OSError as e: - print("Error: %s - %s." % (e.filename, e.strerror)) - - -def test_lancedb_duplicates_throw_warning(caplog): - db = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.db.add(ids=["0"], documents=["doc1"], metadatas=["test"]) - app.db.add(ids=["0"], documents=["doc1"], metadatas=["test"]) - assert "Insert of existing doc ID: 0" not in caplog.text - assert "Add of existing doc ID: 0" not in caplog.text - app.db.reset() - - -def test_lancedb_duplicates_collections_no_warning(caplog): - db = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.set_collection_name("test_collection_1") - app.db.add(ids=["0"], documents=["doc1"], metadatas=["test"]) - app.set_collection_name("test_collection_2") - app.db.add(ids=["0"], documents=["doc1"], metadatas=["test"]) - assert "Insert of existing doc ID: 0" not in caplog.text - assert "Add of existing doc ID: 0" not in caplog.text - app.db.reset() - app.set_collection_name("test_collection_1") - app.db.reset() - - -def test_lancedb_collection_init_with_default_collection(): - db = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - assert app.db.collection.name == "embedchain_store" - - -def test_lancedb_collection_init_with_custom_collection(): - db = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.set_collection_name(name="test_collection") - assert app.db.collection.name == "test_collection" - - -def test_lancedb_collection_set_collection_name(): - db = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.set_collection_name("test_collection") - assert app.db.collection.name == "test_collection" - - -def test_lancedb_collection_changes_encapsulated(): - db = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.set_collection_name("test_collection_1") - assert app.db.count() == 0 - app.db.add(ids=["0"], documents=["doc1"], metadatas=["test"]) - assert app.db.count() == 1 - - app.set_collection_name("test_collection_2") - assert app.db.count() == 0 - - app.db.add(ids=["0"], documents=["doc1"], metadatas=["test"]) - app.set_collection_name("test_collection_1") - assert app.db.count() == 1 - app.db.reset() - app.set_collection_name("test_collection_2") - app.db.reset() - - -def test_lancedb_collection_collections_are_persistent(): - db = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.set_collection_name("test_collection_1") - app.db.add(ids=["0"], documents=["doc1"], metadatas=["test"]) - del app - - db = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app = App(config=AppConfig(collect_metrics=False), db=db) - app.set_collection_name("test_collection_1") - assert app.db.count() == 1 - - app.db.reset() - - -def test_lancedb_collection_parallel_collections(): - db1 = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db", collection_name="test_collection_1")) - app1 = App( - config=AppConfig(collect_metrics=False), - db=db1, - ) - db2 = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db", collection_name="test_collection_2")) - app2 = App( - config=AppConfig(collect_metrics=False), - db=db2, - ) - - # cleanup if any previous tests failed or were interrupted - app1.db.reset() - app2.db.reset() - - app1.db.add(ids=["0"], documents=["doc1"], metadatas=["test"]) - - assert app1.db.count() == 1 - assert app2.db.count() == 0 - - app1.db.add(ids=["1", "2"], documents=["doc1", "doc2"], metadatas=["test", "test"]) - app2.db.add(ids=["0"], documents=["doc1"], metadatas=["test"]) - - app1.set_collection_name("test_collection_2") - assert app1.db.count() == 1 - app2.set_collection_name("test_collection_1") - assert app2.db.count() == 3 - - # cleanup - app1.db.reset() - app2.db.reset() - - -def test_lancedb_collection_ids_share_collections(): - db1 = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app1 = App(config=AppConfig(collect_metrics=False), db=db1) - app1.set_collection_name("one_collection") - db2 = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app2 = App(config=AppConfig(collect_metrics=False), db=db2) - app2.set_collection_name("one_collection") - - # cleanup - app1.db.reset() - app2.db.reset() - - app1.db.add(ids=["0", "1"], documents=["doc1", "doc2"], metadatas=["test", "test"]) - app2.db.add(ids=["2"], documents=["doc3"], metadatas=["test"]) - - assert app1.db.count() == 2 - assert app2.db.count() == 3 - - # cleanup - app1.db.reset() - app2.db.reset() - - -def test_lancedb_collection_reset(): - db1 = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app1 = App(config=AppConfig(collect_metrics=False), db=db1) - app1.set_collection_name("one_collection") - db2 = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app2 = App(config=AppConfig(collect_metrics=False), db=db2) - app2.set_collection_name("two_collection") - db3 = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app3 = App(config=AppConfig(collect_metrics=False), db=db3) - app3.set_collection_name("three_collection") - db4 = LanceDB(config=LanceDBConfig(allow_reset=True, dir="test-db")) - app4 = App(config=AppConfig(collect_metrics=False), db=db4) - app4.set_collection_name("four_collection") - - # cleanup if any previous tests failed or were interrupted - app1.db.reset() - app2.db.reset() - app3.db.reset() - app4.db.reset() - - app1.db.add(ids=["1"], documents=["doc1"], metadatas=["test"]) - app2.db.add(ids=["2"], documents=["doc2"], metadatas=["test"]) - app3.db.add(ids=["3"], documents=["doc3"], metadatas=["test"]) - app4.db.add(ids=["4"], documents=["doc4"], metadatas=["test"]) - - app1.db.reset() - - assert app1.db.count() == 0 - assert app2.db.count() == 1 - assert app3.db.count() == 1 - assert app4.db.count() == 1 - - # cleanup - app2.db.reset() - app3.db.reset() - app4.db.reset() - - -def generate_embeddings(dummy_embed, embed_size): - generated_embedding = [] - for i in range(embed_size): - generated_embedding.append(dummy_embed) - - return generated_embedding diff --git a/embedchain/tests/vectordb/test_pinecone.py b/embedchain/tests/vectordb/test_pinecone.py deleted file mode 100644 index 00051ed94..000000000 --- a/embedchain/tests/vectordb/test_pinecone.py +++ /dev/null @@ -1,225 +0,0 @@ -import pytest - -from embedchain.config.vector_db.pinecone import PineconeDBConfig -from embedchain.vectordb.pinecone import PineconeDB - - -@pytest.fixture -def pinecone_pod_config(): - return PineconeDBConfig( - index_name="test_collection", - api_key="test_api_key", - vector_dimension=3, - pod_config={"environment": "test_environment", "metadata_config": {"indexed": ["*"]}}, - ) - - -@pytest.fixture -def pinecone_serverless_config(): - return PineconeDBConfig( - index_name="test_collection", - api_key="test_api_key", - vector_dimension=3, - serverless_config={ - "cloud": "test_cloud", - "region": "test_region", - }, - ) - - -def test_pinecone_init_without_config(monkeypatch): - monkeypatch.setenv("PINECONE_API_KEY", "test_api_key") - monkeypatch.setattr("embedchain.vectordb.pinecone.PineconeDB._setup_pinecone_index", lambda x: x) - monkeypatch.setattr("embedchain.vectordb.pinecone.PineconeDB._get_or_create_db", lambda x: x) - pinecone_db = PineconeDB() - - assert isinstance(pinecone_db, PineconeDB) - assert isinstance(pinecone_db.config, PineconeDBConfig) - assert pinecone_db.config.pod_config == {"environment": "gcp-starter", "metadata_config": {"indexed": ["*"]}} - monkeypatch.delenv("PINECONE_API_KEY") - - -def test_pinecone_init_with_config(pinecone_pod_config, monkeypatch): - monkeypatch.setattr("embedchain.vectordb.pinecone.PineconeDB._setup_pinecone_index", lambda x: x) - monkeypatch.setattr("embedchain.vectordb.pinecone.PineconeDB._get_or_create_db", lambda x: x) - pinecone_db = PineconeDB(config=pinecone_pod_config) - - assert isinstance(pinecone_db, PineconeDB) - assert isinstance(pinecone_db.config, PineconeDBConfig) - - assert pinecone_db.config.pod_config == pinecone_pod_config.pod_config - - pinecone_db = PineconeDB(config=pinecone_pod_config) - - assert isinstance(pinecone_db, PineconeDB) - assert isinstance(pinecone_db.config, PineconeDBConfig) - - assert pinecone_db.config.serverless_config == pinecone_pod_config.serverless_config - - -class MockListIndexes: - def names(self): - return ["test_collection"] - - -class MockPineconeIndex: - db = [] - - def __init__(*args, **kwargs): - pass - - def upsert(self, chunk, **kwargs): - self.db.extend([c for c in chunk]) - return - - def delete(self, *args, **kwargs): - pass - - def query(self, *args, **kwargs): - return { - "matches": [ - { - "metadata": { - "key": "value", - "text": "text_1", - }, - "score": 0.1, - }, - { - "metadata": { - "key": "value", - "text": "text_2", - }, - "score": 0.2, - }, - ] - } - - def fetch(self, *args, **kwargs): - return { - "vectors": { - "key_1": { - "metadata": { - "source": "1", - } - }, - "key_2": { - "metadata": { - "source": "2", - } - }, - } - } - - def describe_index_stats(self, *args, **kwargs): - return {"total_vector_count": len(self.db)} - - -class MockPineconeClient: - def __init__(*args, **kwargs): - pass - - def list_indexes(self): - return MockListIndexes() - - def create_index(self, *args, **kwargs): - pass - - def Index(self, *args, **kwargs): - return MockPineconeIndex() - - def delete_index(self, *args, **kwargs): - pass - - -class MockPinecone: - def __init__(*args, **kwargs): - pass - - def Pinecone(*args, **kwargs): - return MockPineconeClient() - - def PodSpec(*args, **kwargs): - pass - - def ServerlessSpec(*args, **kwargs): - pass - - -class MockEmbedder: - def embedding_fn(self, documents): - return [[1, 1, 1] for d in documents] - - -def test_setup_pinecone_index(pinecone_pod_config, pinecone_serverless_config, monkeypatch): - monkeypatch.setattr("embedchain.vectordb.pinecone.pinecone", MockPinecone) - monkeypatch.setenv("PINECONE_API_KEY", "test_api_key") - pinecone_db = PineconeDB(config=pinecone_pod_config) - pinecone_db._setup_pinecone_index() - - assert pinecone_db.client is not None - assert pinecone_db.config.index_name == "test_collection" - assert pinecone_db.client.list_indexes().names() == ["test_collection"] - assert pinecone_db.pinecone_index is not None - - pinecone_db = PineconeDB(config=pinecone_serverless_config) - pinecone_db._setup_pinecone_index() - - assert pinecone_db.client is not None - assert pinecone_db.config.index_name == "test_collection" - assert pinecone_db.client.list_indexes().names() == ["test_collection"] - assert pinecone_db.pinecone_index is not None - - -def test_get(monkeypatch): - def mock_pinecone_db(): - monkeypatch.setenv("PINECONE_API_KEY", "test_api_key") - monkeypatch.setattr("embedchain.vectordb.pinecone.PineconeDB._setup_pinecone_index", lambda x: x) - monkeypatch.setattr("embedchain.vectordb.pinecone.PineconeDB._get_or_create_db", lambda x: x) - db = PineconeDB() - db.pinecone_index = MockPineconeIndex() - return db - - pinecone_db = mock_pinecone_db() - ids = pinecone_db.get(["key_1", "key_2"]) - assert ids == {"ids": ["key_1", "key_2"], "metadatas": [{"source": "1"}, {"source": "2"}]} - - -def test_add(monkeypatch): - def mock_pinecone_db(): - monkeypatch.setenv("PINECONE_API_KEY", "test_api_key") - monkeypatch.setattr("embedchain.vectordb.pinecone.PineconeDB._setup_pinecone_index", lambda x: x) - monkeypatch.setattr("embedchain.vectordb.pinecone.PineconeDB._get_or_create_db", lambda x: x) - db = PineconeDB() - db.pinecone_index = MockPineconeIndex() - db._set_embedder(MockEmbedder()) - return db - - pinecone_db = mock_pinecone_db() - pinecone_db.add(["text_1", "text_2"], [{"key_1": "value_1"}, {"key_2": "value_2"}], ["key_1", "key_2"]) - assert pinecone_db.count() == 2 - - pinecone_db.add(["text_3", "text_4"], [{"key_3": "value_3"}, {"key_4": "value_4"}], ["key_3", "key_4"]) - assert pinecone_db.count() == 4 - - -def test_query(monkeypatch): - def mock_pinecone_db(): - monkeypatch.setenv("PINECONE_API_KEY", "test_api_key") - monkeypatch.setattr("embedchain.vectordb.pinecone.PineconeDB._setup_pinecone_index", lambda x: x) - monkeypatch.setattr("embedchain.vectordb.pinecone.PineconeDB._get_or_create_db", lambda x: x) - db = PineconeDB() - db.pinecone_index = MockPineconeIndex() - db._set_embedder(MockEmbedder()) - return db - - pinecone_db = mock_pinecone_db() - # without citations - results = pinecone_db.query(["text_1", "text_2"], n_results=2, where={}) - assert results == ["text_1", "text_2"] - # with citations - results = pinecone_db.query(["text_1", "text_2"], n_results=2, where={}, citations=True) - assert results == [ - ("text_1", {"key": "value", "text": "text_1", "score": 0.1}), - ("text_2", {"key": "value", "text": "text_2", "score": 0.2}), - ] diff --git a/embedchain/tests/vectordb/test_qdrant.py b/embedchain/tests/vectordb/test_qdrant.py deleted file mode 100644 index b2b3dfa07..000000000 --- a/embedchain/tests/vectordb/test_qdrant.py +++ /dev/null @@ -1,167 +0,0 @@ -import unittest -import uuid - -from mock import patch -from qdrant_client.http import models -from qdrant_client.http.models import Batch - -from embedchain import App -from embedchain.config import AppConfig -from embedchain.config.vector_db.pinecone import PineconeDBConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.vectordb.qdrant import QdrantDB - - -def mock_embedding_fn(texts: list[str]) -> list[list[float]]: - """A mock embedding function.""" - return [[1, 2, 3], [4, 5, 6]] - - -class TestQdrantDB(unittest.TestCase): - TEST_UUIDS = ["abc", "def", "ghi"] - - def test_incorrect_config_throws_error(self): - """Test the init method of the Qdrant class throws error for incorrect config""" - with self.assertRaises(TypeError): - QdrantDB(config=PineconeDBConfig()) - - @patch("embedchain.vectordb.qdrant.QdrantClient") - def test_initialize(self, qdrant_client_mock): - # Set the embedder - embedder = BaseEmbedder() - embedder.set_vector_dimension(1536) - embedder.set_embedding_fn(mock_embedding_fn) - - # Create a Qdrant instance - db = QdrantDB() - app_config = AppConfig(collect_metrics=False) - App(config=app_config, db=db, embedding_model=embedder) - - self.assertEqual(db.collection_name, "embedchain-store-1536") - self.assertEqual(db.client, qdrant_client_mock.return_value) - qdrant_client_mock.return_value.get_collections.assert_called_once() - - @patch("embedchain.vectordb.qdrant.QdrantClient") - def test_get(self, qdrant_client_mock): - qdrant_client_mock.return_value.scroll.return_value = ([], None) - - # Set the embedder - embedder = BaseEmbedder() - embedder.set_vector_dimension(1536) - embedder.set_embedding_fn(mock_embedding_fn) - - # Create a Qdrant instance - db = QdrantDB() - app_config = AppConfig(collect_metrics=False) - App(config=app_config, db=db, embedding_model=embedder) - - resp = db.get(ids=[], where={}) - self.assertEqual(resp, {"ids": [], "metadatas": []}) - resp2 = db.get(ids=["123", "456"], where={"url": "https://ai.ai"}) - self.assertEqual(resp2, {"ids": [], "metadatas": []}) - - @patch("embedchain.vectordb.qdrant.QdrantClient") - @patch.object(uuid, "uuid4", side_effect=TEST_UUIDS) - def test_add(self, uuid_mock, qdrant_client_mock): - qdrant_client_mock.return_value.scroll.return_value = ([], None) - - # Set the embedder - embedder = BaseEmbedder() - embedder.set_vector_dimension(1536) - embedder.set_embedding_fn(mock_embedding_fn) - - # Create a Qdrant instance - db = QdrantDB() - app_config = AppConfig(collect_metrics=False) - App(config=app_config, db=db, embedding_model=embedder) - - documents = ["This is a test document.", "This is another test document."] - metadatas = [{}, {}] - ids = ["123", "456"] - db.add(documents, metadatas, ids) - qdrant_client_mock.return_value.upsert.assert_called_once_with( - collection_name="embedchain-store-1536", - points=Batch( - ids=["123", "456"], - payloads=[ - { - "identifier": "123", - "text": "This is a test document.", - "metadata": {"text": "This is a test document."}, - }, - { - "identifier": "456", - "text": "This is another test document.", - "metadata": {"text": "This is another test document."}, - }, - ], - vectors=[[1, 2, 3], [4, 5, 6]], - ), - ) - - @patch("embedchain.vectordb.qdrant.QdrantClient") - def test_query(self, qdrant_client_mock): - # Set the embedder - embedder = BaseEmbedder() - embedder.set_vector_dimension(1536) - embedder.set_embedding_fn(mock_embedding_fn) - - # Create a Qdrant instance - db = QdrantDB() - app_config = AppConfig(collect_metrics=False) - App(config=app_config, db=db, embedding_model=embedder) - - # Query for the document. - db.query(input_query="This is a test document.", n_results=1, where={"doc_id": "123"}) - - qdrant_client_mock.return_value.search.assert_called_once_with( - collection_name="embedchain-store-1536", - query_filter=models.Filter( - must=[ - models.FieldCondition( - key="metadata.doc_id", - match=models.MatchValue( - value="123", - ), - ) - ] - ), - query_vector=[1, 2, 3], - limit=1, - ) - - @patch("embedchain.vectordb.qdrant.QdrantClient") - def test_count(self, qdrant_client_mock): - # Set the embedder - embedder = BaseEmbedder() - embedder.set_vector_dimension(1536) - embedder.set_embedding_fn(mock_embedding_fn) - - # Create a Qdrant instance - db = QdrantDB() - app_config = AppConfig(collect_metrics=False) - App(config=app_config, db=db, embedding_model=embedder) - - db.count() - qdrant_client_mock.return_value.get_collection.assert_called_once_with(collection_name="embedchain-store-1536") - - @patch("embedchain.vectordb.qdrant.QdrantClient") - def test_reset(self, qdrant_client_mock): - # Set the embedder - embedder = BaseEmbedder() - embedder.set_vector_dimension(1536) - embedder.set_embedding_fn(mock_embedding_fn) - - # Create a Qdrant instance - db = QdrantDB() - app_config = AppConfig(collect_metrics=False) - App(config=app_config, db=db, embedding_model=embedder) - - db.reset() - qdrant_client_mock.return_value.delete_collection.assert_called_once_with( - collection_name="embedchain-store-1536" - ) - - -if __name__ == "__main__": - unittest.main() diff --git a/embedchain/tests/vectordb/test_weaviate.py b/embedchain/tests/vectordb/test_weaviate.py deleted file mode 100644 index a51870d44..000000000 --- a/embedchain/tests/vectordb/test_weaviate.py +++ /dev/null @@ -1,237 +0,0 @@ -import unittest -from unittest.mock import patch - -from embedchain import App -from embedchain.config import AppConfig -from embedchain.config.vector_db.pinecone import PineconeDBConfig -from embedchain.embedder.base import BaseEmbedder -from embedchain.vectordb.weaviate import WeaviateDB - - -def mock_embedding_fn(texts: list[str]) -> list[list[float]]: - """A mock embedding function.""" - return [[1, 2, 3], [4, 5, 6]] - - -class TestWeaviateDb(unittest.TestCase): - def test_incorrect_config_throws_error(self): - """Test the init method of the WeaviateDb class throws error for incorrect config""" - with self.assertRaises(TypeError): - WeaviateDB(config=PineconeDBConfig()) - - @patch("embedchain.vectordb.weaviate.weaviate") - def test_initialize(self, weaviate_mock): - """Test the init method of the WeaviateDb class.""" - weaviate_client_mock = weaviate_mock.Client.return_value - weaviate_client_schema_mock = weaviate_client_mock.schema - - # Mock that schema doesn't already exist so that a new schema is created - weaviate_client_schema_mock.exists.return_value = False - # Set the embedder - embedder = BaseEmbedder() - embedder.set_vector_dimension(1536) - embedder.set_embedding_fn(mock_embedding_fn) - - # Create a Weaviate instance - db = WeaviateDB() - app_config = AppConfig(collect_metrics=False) - App(config=app_config, db=db, embedding_model=embedder) - - expected_class_obj = { - "classes": [ - { - "class": "Embedchain_store_1536", - "vectorizer": "none", - "properties": [ - { - "name": "identifier", - "dataType": ["text"], - }, - { - "name": "text", - "dataType": ["text"], - }, - { - "name": "metadata", - "dataType": ["Embedchain_store_1536_metadata"], - }, - ], - }, - { - "class": "Embedchain_store_1536_metadata", - "vectorizer": "none", - "properties": [ - { - "name": "data_type", - "dataType": ["text"], - }, - { - "name": "doc_id", - "dataType": ["text"], - }, - { - "name": "url", - "dataType": ["text"], - }, - { - "name": "hash", - "dataType": ["text"], - }, - { - "name": "app_id", - "dataType": ["text"], - }, - ], - }, - ] - } - - # Assert that the Weaviate client was initialized - weaviate_mock.Client.assert_called_once() - self.assertEqual(db.index_name, "Embedchain_store_1536") - weaviate_client_schema_mock.create.assert_called_once_with(expected_class_obj) - - @patch("embedchain.vectordb.weaviate.weaviate") - def test_get_or_create_db(self, weaviate_mock): - """Test the _get_or_create_db method of the WeaviateDb class.""" - weaviate_client_mock = weaviate_mock.Client.return_value - - embedder = BaseEmbedder() - embedder.set_vector_dimension(1536) - embedder.set_embedding_fn(mock_embedding_fn) - - # Create a Weaviate instance - db = WeaviateDB() - app_config = AppConfig(collect_metrics=False) - App(config=app_config, db=db, embedding_model=embedder) - - expected_client = db._get_or_create_db() - self.assertEqual(expected_client, weaviate_client_mock) - - @patch("embedchain.vectordb.weaviate.weaviate") - def test_add(self, weaviate_mock): - """Test the add method of the WeaviateDb class.""" - weaviate_client_mock = weaviate_mock.Client.return_value - weaviate_client_batch_mock = weaviate_client_mock.batch - weaviate_client_batch_enter_mock = weaviate_client_mock.batch.__enter__.return_value - - # Set the embedder - embedder = BaseEmbedder() - embedder.set_vector_dimension(1536) - embedder.set_embedding_fn(mock_embedding_fn) - - # Create a Weaviate instance - db = WeaviateDB() - app_config = AppConfig(collect_metrics=False) - App(config=app_config, db=db, embedding_model=embedder) - - documents = ["This is test document"] - metadatas = [None] - ids = ["id_1"] - db.add(documents, metadatas, ids) - - # Check if the document was added to the database. - weaviate_client_batch_mock.configure.assert_called_once_with(batch_size=100, timeout_retries=3) - weaviate_client_batch_enter_mock.add_data_object.assert_any_call( - data_object={"text": documents[0]}, class_name="Embedchain_store_1536_metadata", vector=[1, 2, 3] - ) - - weaviate_client_batch_enter_mock.add_data_object.assert_any_call( - data_object={"text": documents[0]}, - class_name="Embedchain_store_1536_metadata", - vector=[1, 2, 3], - ) - - @patch("embedchain.vectordb.weaviate.weaviate") - def test_query_without_where(self, weaviate_mock): - """Test the query method of the WeaviateDb class.""" - weaviate_client_mock = weaviate_mock.Client.return_value - weaviate_client_query_mock = weaviate_client_mock.query - weaviate_client_query_get_mock = weaviate_client_query_mock.get.return_value - - # Set the embedder - embedder = BaseEmbedder() - embedder.set_vector_dimension(1536) - embedder.set_embedding_fn(mock_embedding_fn) - - # Create a Weaviate instance - db = WeaviateDB() - app_config = AppConfig(collect_metrics=False) - App(config=app_config, db=db, embedding_model=embedder) - - # Query for the document. - db.query(input_query="This is a test document.", n_results=1, where={}) - - weaviate_client_query_mock.get.assert_called_once_with("Embedchain_store_1536", ["text"]) - weaviate_client_query_get_mock.with_near_vector.assert_called_once_with({"vector": [1, 2, 3]}) - - @patch("embedchain.vectordb.weaviate.weaviate") - def test_query_with_where(self, weaviate_mock): - """Test the query method of the WeaviateDb class.""" - weaviate_client_mock = weaviate_mock.Client.return_value - weaviate_client_query_mock = weaviate_client_mock.query - weaviate_client_query_get_mock = weaviate_client_query_mock.get.return_value - weaviate_client_query_get_where_mock = weaviate_client_query_get_mock.with_where.return_value - - # Set the embedder - embedder = BaseEmbedder() - embedder.set_vector_dimension(1536) - embedder.set_embedding_fn(mock_embedding_fn) - - # Create a Weaviate instance - db = WeaviateDB() - app_config = AppConfig(collect_metrics=False) - App(config=app_config, db=db, embedding_model=embedder) - - # Query for the document. - db.query(input_query="This is a test document.", n_results=1, where={"doc_id": "123"}) - - weaviate_client_query_mock.get.assert_called_once_with("Embedchain_store_1536", ["text"]) - weaviate_client_query_get_mock.with_where.assert_called_once_with( - {"operator": "Equal", "path": ["metadata", "Embedchain_store_1536_metadata", "doc_id"], "valueText": "123"} - ) - weaviate_client_query_get_where_mock.with_near_vector.assert_called_once_with({"vector": [1, 2, 3]}) - - @patch("embedchain.vectordb.weaviate.weaviate") - def test_reset(self, weaviate_mock): - """Test the reset method of the WeaviateDb class.""" - weaviate_client_mock = weaviate_mock.Client.return_value - weaviate_client_batch_mock = weaviate_client_mock.batch - - # Set the embedder - embedder = BaseEmbedder() - embedder.set_vector_dimension(1536) - embedder.set_embedding_fn(mock_embedding_fn) - - # Create a Weaviate instance - db = WeaviateDB() - app_config = AppConfig(collect_metrics=False) - App(config=app_config, db=db, embedding_model=embedder) - - # Reset the database. - db.reset() - - weaviate_client_batch_mock.delete_objects.assert_called_once_with( - "Embedchain_store_1536", where={"path": ["identifier"], "operator": "Like", "valueText": ".*"} - ) - - @patch("embedchain.vectordb.weaviate.weaviate") - def test_count(self, weaviate_mock): - """Test the reset method of the WeaviateDb class.""" - weaviate_client_mock = weaviate_mock.Client.return_value - weaviate_client_query = weaviate_client_mock.query - - # Set the embedder - embedder = BaseEmbedder() - embedder.set_vector_dimension(1536) - embedder.set_embedding_fn(mock_embedding_fn) - - # Create a Weaviate instance - db = WeaviateDB() - app_config = AppConfig(collect_metrics=False) - App(config=app_config, db=db, embedding_model=embedder) - - # Reset the database. - db.count() - - weaviate_client_query.aggregate.assert_called_once_with("Embedchain_store_1536") diff --git a/embedchain/tests/vectordb/test_zilliz_db.py b/embedchain/tests/vectordb/test_zilliz_db.py deleted file mode 100644 index 7d6360442..000000000 --- a/embedchain/tests/vectordb/test_zilliz_db.py +++ /dev/null @@ -1,168 +0,0 @@ -# ruff: noqa: E501 - -import os -from unittest import mock -from unittest.mock import Mock, patch - -import pytest - -from embedchain.config import ZillizDBConfig -from embedchain.vectordb.zilliz import ZillizVectorDB - - -# to run tests, provide the URI and TOKEN in .env file -class TestZillizVectorDBConfig: - @mock.patch.dict(os.environ, {"ZILLIZ_CLOUD_URI": "mocked_uri", "ZILLIZ_CLOUD_TOKEN": "mocked_token"}) - def test_init_with_uri_and_token(self): - """ - Test if the `ZillizVectorDBConfig` instance is initialized with the correct uri and token values. - """ - # Create a ZillizDBConfig instance with mocked values - expected_uri = "mocked_uri" - expected_token = "mocked_token" - db_config = ZillizDBConfig() - - # Assert that the values in the ZillizVectorDB instance match the mocked values - assert db_config.uri == expected_uri - assert db_config.token == expected_token - - @mock.patch.dict(os.environ, {"ZILLIZ_CLOUD_URI": "mocked_uri", "ZILLIZ_CLOUD_TOKEN": "mocked_token"}) - def test_init_without_uri(self): - """ - Test if the `ZillizVectorDBConfig` instance throws an error when no URI found. - """ - try: - del os.environ["ZILLIZ_CLOUD_URI"] - except KeyError: - pass - - with pytest.raises(AttributeError): - ZillizDBConfig() - - @mock.patch.dict(os.environ, {"ZILLIZ_CLOUD_URI": "mocked_uri", "ZILLIZ_CLOUD_TOKEN": "mocked_token"}) - def test_init_without_token(self): - """ - Test if the `ZillizVectorDBConfig` instance throws an error when no Token found. - """ - try: - del os.environ["ZILLIZ_CLOUD_TOKEN"] - except KeyError: - pass - # Test if an exception is raised when ZILLIZ_CLOUD_TOKEN is missing - with pytest.raises(AttributeError): - ZillizDBConfig() - - -class TestZillizVectorDB: - @pytest.fixture - @mock.patch.dict(os.environ, {"ZILLIZ_CLOUD_URI": "mocked_uri", "ZILLIZ_CLOUD_TOKEN": "mocked_token"}) - def mock_config(self, mocker): - return mocker.Mock(spec=ZillizDBConfig()) - - @patch("embedchain.vectordb.zilliz.MilvusClient", autospec=True) - @patch("embedchain.vectordb.zilliz.connections.connect", autospec=True) - def test_zilliz_vector_db_setup(self, mock_connect, mock_client, mock_config): - """ - Test if the `ZillizVectorDB` instance is initialized with the correct uri and token values. - """ - # Create an instance of ZillizVectorDB with the mock config - # zilliz_db = ZillizVectorDB(config=mock_config) - ZillizVectorDB(config=mock_config) - - # Assert that the MilvusClient and connections.connect were called - mock_client.assert_called_once_with(uri=mock_config.uri, token=mock_config.token) - mock_connect.assert_called_once_with(uri=mock_config.uri, token=mock_config.token) - - -class TestZillizDBCollection: - @pytest.fixture - @mock.patch.dict(os.environ, {"ZILLIZ_CLOUD_URI": "mocked_uri", "ZILLIZ_CLOUD_TOKEN": "mocked_token"}) - def mock_config(self, mocker): - return mocker.Mock(spec=ZillizDBConfig()) - - @pytest.fixture - def mock_embedder(self, mocker): - return mocker.Mock() - - @mock.patch.dict(os.environ, {"ZILLIZ_CLOUD_URI": "mocked_uri", "ZILLIZ_CLOUD_TOKEN": "mocked_token"}) - def test_init_with_default_collection(self): - """ - Test if the `ZillizVectorDB` instance is initialized with the correct default collection name. - """ - # Create a ZillizDBConfig instance - db_config = ZillizDBConfig() - - assert db_config.collection_name == "embedchain_store" - - @mock.patch.dict(os.environ, {"ZILLIZ_CLOUD_URI": "mocked_uri", "ZILLIZ_CLOUD_TOKEN": "mocked_token"}) - def test_init_with_custom_collection(self): - """ - Test if the `ZillizVectorDB` instance is initialized with the correct custom collection name. - """ - # Create a ZillizDBConfig instance with mocked values - - expected_collection = "test_collection" - db_config = ZillizDBConfig(collection_name="test_collection") - - assert db_config.collection_name == expected_collection - - @patch("embedchain.vectordb.zilliz.MilvusClient", autospec=True) - @patch("embedchain.vectordb.zilliz.connections", autospec=True) - def test_query(self, mock_connect, mock_client, mock_embedder, mock_config): - # Create an instance of ZillizVectorDB with mock config - zilliz_db = ZillizVectorDB(config=mock_config) - - # Add a 'embedder' attribute to the ZillizVectorDB instance for testing - zilliz_db.embedder = mock_embedder # Mock the 'collection' object - - # Add a 'collection' attribute to the ZillizVectorDB instance for testing - zilliz_db.collection = Mock(is_empty=False) # Mock the 'collection' object - - assert zilliz_db.client == mock_client() - - # Mock the MilvusClient search method - with patch.object(zilliz_db.client, "search") as mock_search: - # Mock the embedding function - mock_embedder.embedding_fn.return_value = ["query_vector"] - - # Mock the search result - mock_search.return_value = [ - [ - { - "distance": 0.0, - "entity": { - "text": "result_doc", - "embeddings": [1, 2, 3], - "metadata": {"url": "url_1", "doc_id": "doc_id_1"}, - }, - } - ] - ] - - query_result = zilliz_db.query(input_query="query_text", n_results=1, where={}) - - # Assert that MilvusClient.search was called with the correct parameters - mock_search.assert_called_with( - collection_name=mock_config.collection_name, - data=["query_vector"], - filter="", - limit=1, - output_fields=["*"], - ) - - # Assert that the query result matches the expected result - assert query_result == ["result_doc"] - - query_result_with_citations = zilliz_db.query( - input_query="query_text", n_results=1, where={}, citations=True - ) - - mock_search.assert_called_with( - collection_name=mock_config.collection_name, - data=["query_vector"], - filter="", - limit=1, - output_fields=["*"], - ) - - assert query_result_with_citations == [("result_doc", {"url": "url_1", "doc_id": "doc_id_1", "score": 0.0})] diff --git a/pyproject.toml b/pyproject.toml index a2517b5ad..2b1e99410 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -145,7 +145,7 @@ test = [ [tool.ruff] line-length = 120 -exclude = ["embedchain/", "openmemory/"] +exclude = ["openmemory/"] [tool.ruff.lint.isort] known-first-party = ["mem0", "mem0_cli"]