diff --git a/.github/workflows/pre-release-CI.yml b/.github/workflows/pre-release-CI.yml index 8dd94fd0..a943abac 100644 --- a/.github/workflows/pre-release-CI.yml +++ b/.github/workflows/pre-release-CI.yml @@ -38,7 +38,7 @@ jobs: - name: Install the wheel run: | - pip install dist/pinecone_resin*.whl + pip install dist/pinecone_canopy*.whl - name: Create dev requirements file run: | diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + 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 [yyyy] [name of copyright owner] + + 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/README.md b/README.md index f1999cf0..cbcdc7e3 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# Resin +# Canopy -**Resin** is a Sofware Development Kit (SDK) for AI applications. Resin allows you to test, build and package Retrieval Augmented Applications with Pinecone Vector Database. **Resin** is desinged to be well packaged and easy to use. It can be used as-a-library or as-a-service and designed to be modular, so you can use only the parts that you need. **Resin** ships with a developer friendly CLI, to help you kickoff and test your application quickly. +**Canopy** is a Sofware Development Kit (SDK) for AI applications. Canopy allows you to test, build and package Retrieval Augmented Applications with Pinecone Vector Database. **Canopy** is desinged to be well packaged and easy to use. It can be used as-a-library or as-a-service and designed to be modular, so you can use only the parts that you need. **Canopy** ships with a developer friendly CLI, to help you kickoff and test your application quickly. -## RAG with Resin +## RAG with Canopy **Pinecone + LLM = ❤️** -By enhancing language models with access to unlearned knowledge and inifinite memory we can build AI applications that can answer questions and assist humans without the risk of hallucinating or generating fake content. Let's learn how Resin executes RAG pipeline. +By enhancing language models with access to unlearned knowledge and inifinite memory we can build AI applications that can answer questions and assist humans without the risk of hallucinating or generating fake content. Let's learn how Canopy executes RAG pipeline. ![](.readme-content/rag_flow.png) @@ -14,13 +14,13 @@ By enhancing language models with access to unlearned knowledge and inifinite me Chat Flow (click to expand) -1. User will promt a question to Resin /chat/completions endpoint. -2. resin will use a language model to break down the questions into queries, sometimes, a single user ask may result in multiple knowledge queries. -3. Resin will encode and embed each query seperateley. -4. Resin will query pinecone with the embedded queries and will fetch back K results for each. Resin will determine how many results it needs to fetch based on the token budget set by the user -5. Now resin has all the external knowledge needed to answer the original question, Resin will perform a _context building_ step to create an on-bugdet optimal context. -6. Resin will generate a prompt combining general task information and the system message and sent the prompt+context to the language model. -7. Resin will decode the response from the language model and will return the response in the API response (or in streaming). +1. User will promt a question to Canopy /chat/completions endpoint. +2. canopy will use a language model to break down the questions into queries, sometimes, a single user ask may result in multiple knowledge queries. +3. Canopy will encode and embed each query seperateley. +4. Canopy will query pinecone with the embedded queries and will fetch back K results for each. Canopy will determine how many results it needs to fetch based on the token budget set by the user +5. Now canopy has all the external knowledge needed to answer the original question, Canopy will perform a _context building_ step to create an on-bugdet optimal context. +6. Canopy will generate a prompt combining general task information and the system message and sent the prompt+context to the language model. +7. Canopy will decode the response from the language model and will return the response in the API response (or in streaming). @@ -31,51 +31,51 @@ By enhancing language models with access to unlearned knowledge and inifinite me
  1. User will call /context/upsert with Documents - each document with id, text, and optinally source and metadata
  2. -
  3. Resin KnowledgeBase will process the documents and chunk ecah document in a structural and semantic way
  4. +
  5. Canopy KnowledgeBase will process the documents and chunk ecah document in a structural and semantic way
  6. -
  7. Resin KnowledgeBase will encode each chunk using one or more embedding models
  8. +
  9. Canopy KnowledgeBase will encode each chunk using one or more embedding models
  10. -
  11. Resin KnowledgeBase will upsert the encoded chunks into Pinecone Index
  12. +
  13. Canopy KnowledgeBase will upsert the encoded chunks into Pinecone Index
-## Why Resin? [TODO: TBD] +## Why Canopy? [TODO: TBD] -* **Ease of use** - Installed with a single command and can deploy an AI application in minutes. **Resin** is designed to be easy to use and easy to integrate with your existing applications and compatible with OpenAI /chat/completions API. +* **Ease of use** - Installed with a single command and can deploy an AI application in minutes. **Canopy** is designed to be easy to use and easy to integrate with your existing applications and compatible with OpenAI /chat/completions API. -* **Operational & Production ready** - Resin is built on top of **Pinecone** and can Scale to Billions of documents. Unlike other AI frameworks, **Resin** optimizes for production use cases it allows developers to set up operating point to have better control over token consumption in prompt or in generation. **Resin** can maximize context quality and relevance while controlling the cost of the AI system. +* **Operational & Production ready** - Canopy is built on top of **Pinecone** and can Scale to Billions of documents. Unlike other AI frameworks, **Canopy** optimizes for production use cases it allows developers to set up operating point to have better control over token consumption in prompt or in generation. **Canopy** can maximize context quality and relevance while controlling the cost of the AI system. -* **Open source** - **Resin** is open source and free to use. It is also designed to be open and extensible, so you can easily add your own components and extend the functionality. +* **Open source** - **Canopy** is open source and free to use. It is also designed to be open and extensible, so you can easily add your own components and extend the functionality. ## What's inside the box? -1. **Resin Core Library** - Resin has 3 high level classes that act as API level components: +1. **Canopy Core Library** - Canopy has 3 high level classes that act as API level components: * **ChatEngine** _`/chat/completions`_ - is a complete RAG unit that exposes a chat interface of LLM augmented with retrieval engine. * **ContextEngine** _`/context/query`_ - is a proxy between your application and Pinecone. It will handle the R in the RAG pipeline and will return the snippet of context along with the respected source. * **KnowledgeBase** _`/context/{upsert, delete}` - is the data managment interface, handles the processing, chunking and encoding (embedding) of the data, along with Upsert and Delete operations > more information about the Core Library usage can be found in the [Library Documentation](docs/library.md) -2. **Resin Service** - a webservice that wraps the **Resin Core** and exposes it as a REST API. The service is built on top of FastAPI, Uvicorn and Gunicorn and can be easily deployed in production. +2. **Canopy Service** - a webservice that wraps the **Canopy Core** and exposes it as a REST API. The service is built on top of FastAPI, Uvicorn and Gunicorn and can be easily deployed in production. > For the complete documentation please go to: [#TODO: LINK](link.link.com) -3. **Resin CLI** - Resin comes with a fully functional CLI that is purposley built to allow users to quickly test their configuration and application before shipping, the CLI also comes with managment operations that allow you to create indexes and load data quickly +3. **Canopy CLI** - Canopy comes with a fully functional CLI that is purposley built to allow users to quickly test their configuration and application before shipping, the CLI also comes with managment operations that allow you to create indexes and load data quickly ## Setup 0. set up a virtual environment (optional) ```bash -python3 -m venv resin-env -source resin-env/bin/activate +python3 -m venv canopy-env +source canopy-env/bin/activate ``` more about virtual environments [here](https://docs.python.org/3/tutorial/venv.html) 1. install the package ```bash -pip install pinecone-resin +pip install pinecone-canopy ``` 2. Set up the environment variables @@ -98,58 +98,58 @@ export INDEX_NAME= | `PINECONE_API_KEY` | The API key for Pinecone. Used to authenticate to Pinecone services to create indexes and to insert, delete and search data | Register or log into your Pinecone account in the [console](https://app.pinecone.io/). You can access your API key from the "API Keys" section in the sidebar of your dashboard | | `PINECONE_ENVIRONMENT`| Determines the Pinecone service cloud environment of your index e.g `west1-gcp`, `us-east-1-aws`, etc | You can find the Pinecone environment next to the API key in [console](https://app.pinecone.io/) | | `OPENAI_API_KEY` | API key for OpenAI. Used to authenticate to OpenAI's services for embedding and chat API | You can find your OpenAI API key [here](https://platform.openai.com/account/api-keys). You might need to login or register to OpenAI services | -| `INDEX_NAME` | Name of the Pinecone index Resin will underlying work with | You can choose any name as long as it follows Pinecone's [restrictions](https://support.pinecone.io/hc/en-us/articles/11729246212637-Are-there-restrictions-on-index-names-#:~:text=There%20are%20two%20main%20restrictions,and%20emojis%20are%20not%20supported.) | -| `RESIN_CONFIG_FILE` | The path of a configuration yaml file to be used by the Resin service. | Optional - if not provided, default configuration would be used | +| `INDEX_NAME` | Name of the Pinecone index Canopy will underlying work with | You can choose any name as long as it follows Pinecone's [restrictions](https://support.pinecone.io/hc/en-us/articles/11729246212637-Are-there-restrictions-on-index-names-#:~:text=There%20are%20two%20main%20restrictions,and%20emojis%20are%20not%20supported.) | +| `CANOPY_CONFIG_FILE` | The path of a configuration yaml file to be used by the Canopy service. | Optional - if not provided, default configuration would be used | 3. Check that installation is successful and environment is set, run: ```bash -resin +canopy ``` output should be similar to this: ```bash -Resin: Ready +Canopy: Ready -Usage: resin [OPTIONS] COMMAND [ARGS]... +Usage: canopy [OPTIONS] COMMAND [ARGS]... # rest of the help message ``` ## Quickstart -In this quickstart, we will show you how to use the **Resin** to build a simple question answering system using RAG (retrival augmented generation). +In this quickstart, we will show you how to use the **Canopy** to build a simple question answering system using RAG (retrival augmented generation). -### 1. Create a new **Resin** Index +### 1. Create a new **Canopy** Index -**Resin** will create and configure a new Pinecone index on your behalf. Just run: +**Canopy** will create and configure a new Pinecone index on your behalf. Just run: ```bash -resin new +canopy new ``` -And follow the CLI instructions. The index that will be created will have a prefix `resin--`. This will have to be done only once per index. +And follow the CLI instructions. The index that will be created will have a prefix `canopy--`. This will have to be done only once per index. > To learn more about Pinecone Indexes and how to manage them, please refer to the following guide: [Understanding indexes](https://docs.pinecone.io/docs/indexes) -![](.readme-content/resin-new.gif) +![](.readme-content/canopy-new.gif) ### 2. Uploading data -You can load data into your **Resin** Index by simply using the CLI: +You can load data into your **Canopy** Index by simply using the CLI: ```bash -resin upsert /path/to/data_directory +canopy upsert /path/to/data_directory # or -resin upsert /path/to/data_directory/file.parquet +canopy upsert /path/to/data_directory/file.parquet # or -resin upsert /path/to/data_directory/file.jsonl +canopy upsert /path/to/data_directory/file.jsonl ``` -Resin support single or mulitple files in jsonl or praquet format. The documents should have the following schema: +Canopy support single or mulitple files in jsonl or praquet format. The documents should have the following schema: ``` +----------+--------------+--------------+---------------+ @@ -162,34 +162,34 @@ Resin support single or mulitple files in jsonl or praquet format. The documents Follow the instructions in the CLI to upload your data. -![](.readme-content/resin-upsert.gif) +![](.readme-content/canopy-upsert.gif) -### 3. Start the **Resin** service +### 3. Start the **Canopy** service -**Resin** service serve as a proxy between your application and Pinecone. It will also handle the RAG part of the application. To start the service, run: +**Canopy** service serve as a proxy between your application and Pinecone. It will also handle the RAG part of the application. To start the service, run: ```bash -resin start +canopy start ``` Now, you should be prompted with standard Uvicorn logs: ``` -Starting Resin service on 0.0.0.0:8000 +Starting Canopy service on 0.0.0.0:8000 INFO: Started server process [24431] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) ``` -![](.readme-content/resin-start.gif) +![](.readme-content/canopy-start.gif) > **_📝 NOTE:_** > -> The resin start command will keep the terminal occupied. To proceed with the next steps, please open a new terminal window. +> The canopy start command will keep the terminal occupied. To proceed with the next steps, please open a new terminal window. > and make sure all the environment variables described in the [installation](#how-to-install) section are set. -> If you want to run the service in the background, you can use the following command - **```nohup resin start &```** +> If you want to run the service in the background, you can use the following command - **```nohup canopy start &```** ### 4. Chat with your data @@ -197,39 +197,39 @@ INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) Now that you have data in your index, you can chat with it using the CLI: ```bash -resin chat +canopy chat ``` -This will open a chat interface in your terminal. You can ask questions and the **Resin** will try to answer them using the data you uploaded. +This will open a chat interface in your terminal. You can ask questions and the **Canopy** will try to answer them using the data you uploaded. -![](.readme-content/resin-chat.gif) +![](.readme-content/canopy-chat.gif) To compare the chat response with and without RAG use the `--baseline` flag ```bash -resin chat --baseline +canopy chat --baseline ``` This will open a similar chat interface window, but will send your question directly to the LLM without the RAG pipeline. -![](.readme-content/resin-chat-no-rag.gif) +![](.readme-content/canopy-chat-no-rag.gif) -### 5. Stop the **Resin** service +### 5. Stop the **Canopy** service To stop the service, simply press `CTRL+C` in the terminal where you started it. If you have started the service in the background, you can stop it by running: ```bash -resin stop +canopy stop ``` ## Advanced usage -### Migrating existing OpenAI application to **Resin** +### Migrating existing OpenAI application to **Canopy** -If you already have an application that uses the OpenAI API, you can migrate it to **Resin** by simply changing the API endpoint to `http://host:port/context` as follows: +If you already have an application that uses the OpenAI API, you can migrate it to **Canopy** by simply changing the API endpoint to `http://host:port/context` as follows: ```python import openai @@ -247,12 +247,12 @@ import openai openai_response = openai.Completion.create(..., api_base="http://host:port/context") ``` -### Running Resin service in production +### Running Canopy service in production -Resin is using FastAPI as the web framework and Uvicorn as the ASGI server. It is recommended to use Gunicorn as the production server, mainly because it supports multiple worker processes and can handle multiple requests in parallel, more details can be found [here](https://www.uvicorn.org/deployment/#using-a-process-manager). +Canopy is using FastAPI as the web framework and Uvicorn as the ASGI server. It is recommended to use Gunicorn as the production server, mainly because it supports multiple worker processes and can handle multiple requests in parallel, more details can be found [here](https://www.uvicorn.org/deployment/#using-a-process-manager). -To run the resin service for production, please run: +To run the canopy service for production, please run: ```bash -gunicorn resin_cli.app:app --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 --workers +gunicorn canopy_cli.app:app --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 --workers ``` \ No newline at end of file diff --git a/docs/library.md b/docs/library.md index 8136adc2..d916f44f 100644 --- a/docs/library.md +++ b/docs/library.md @@ -1,16 +1,16 @@ -# Resin Library +# Canopy Library -For most common use cases, users can simply deploy the fully-configurable [Resin service](../README.md), which provides a REST API backend for your own RAG-infused Chatbot. +For most common use cases, users can simply deploy the fully-configurable [Canopy service](../README.md), which provides a REST API backend for your own RAG-infused Chatbot. -For advanced users, this page describes how to use `resin` core library directly to implement their own custom applications. +For advanced users, this page describes how to use `canopy` core library directly to implement their own custom applications. -The idea behind Resin library is to provide a framework to build AI applications on top of Pinecone as a long memory storage for you own data. Resin library designed with the following principles in mind: +The idea behind Canopy library is to provide a framework to build AI applications on top of Pinecone as a long memory storage for you own data. Canopy library designed with the following principles in mind: -- **Easy to use**: Resin is designed to be easy to use. It is well packaged and can be installed with a single command. -- **Modularity**: Resin is built as a collection of modules that can be used together or separately. For example, you can use the `chat_engine` module to build a chatbot on top of your data, or you can use the `knowledge_base` module to directly store and search your data. -- **Extensibility**: Resin is designed to be extensible. You can easily add your own components and extend the functionality. -- **Production ready**: Resin designed to be production ready, tested, well documented, maintained and supported. -- **Open source**: Resin is open source and free to use. It built in partnership with the community and for the community. +- **Easy to use**: Canopy is designed to be easy to use. It is well packaged and can be installed with a single command. +- **Modularity**: Canopy is built as a collection of modules that can be used together or separately. For example, you can use the `chat_engine` module to build a chatbot on top of your data, or you can use the `knowledge_base` module to directly store and search your data. +- **Extensibility**: Canopy is designed to be extensible. You can easily add your own components and extend the functionality. +- **Production ready**: Canopy designed to be production ready, tested, well documented, maintained and supported. +- **Open source**: Canopy is open source and free to use. It built in partnership with the community and for the community. ## High level architecture @@ -19,7 +19,7 @@ The idea behind Resin library is to provide a framework to build AI applications ## Setup -To setup resin, please follow the instructions [here](../README.md#setup). +To setup canopy, please follow the instructions [here](../README.md#setup). ## Quickstart @@ -27,19 +27,19 @@ To setup resin, please follow the instructions [here](../README.md#setup). The `Tokenizer` object is used for converting text into tokens, which is the basic data represntation that is used for processing. -Since manny different classes rely on a tokenizer, Resin uses a singleton `Tokenizer` object which needs to be initialized once. +Since manny different classes rely on a tokenizer, Canopy uses a singleton `Tokenizer` object which needs to be initialized once. -Before instantiating any other resin core objects, please initialize the `Tokenizer` singleton: +Before instantiating any other canopy core objects, please initialize the `Tokenizer` singleton: ```python -from resin.tokenizer import Tokenizer +from canopy.tokenizer import Tokenizer Tokenizer.initialize() ``` Then, each time you want to use the tokenizer, you can simply instantiate a local object: ```python -from resin.tokenizer import Tokenizer +from canopy.tokenizer import Tokenizer # no need to pass any parameters, the global tokenizer will be used tokenizer = Tokenizer() @@ -58,7 +58,7 @@ The `Tokenizer` singleton is holding an inner `Tokenizer` object that implements You can create your own customized tokenizer by implementing a new class that derives from `BaseTokenizer`, then passing this class to the `Tokenizer` singleton during initialization. Example: ```python -from resin.tokenizer import Tokenizer, BaseTokenizer +from canopy.tokenizer import Tokenizer, BaseTokenizer class CustomTokenizer(BaseTokenizer): # Implement BaseToknizer's abstract methods, like `def tokenize()` etc. @@ -70,8 +70,8 @@ Tokenizer.initialize(tokenizer_class=CustomTokenizer) When you initialize the `Tokenizer` singleton, you can pass init arguments to the underlying Tokenizer class. Any init argument that is expected by the underlying class's constructor, can be passed as `kwarg` directly to `Tokenizer.initalize()`. For example: ```python -from resin.tokenizer import Tokenizer -from resin.tokenizer.openai import OpenAITokenizer +from canopy.tokenizer import Tokenizer +from canopy.tokenizer.openai import OpenAITokenizer Tokenizer.initialize(tokenizer_class=OpenAITokenizer, model_name="gpt2") ``` @@ -85,15 +85,15 @@ Knowledge base is an object that is responsible for storing and query your data. To create a knowledge base, you can use the following command: ```python -from resin.knowledge_base import KnowledgeBase +from canopy.knowledge_base import KnowledgeBase kb = KnowledgeBase(index_name="my-index") ``` -To create a new Pinecone index and connect it to the knowledge base, you can use the `create_resin_index` method: +To create a new Pinecone index and connect it to the knowledge base, you can use the `create_canopy_index` method: ```python -kb.create_resin_index() +kb.create_canopy_index() ``` Then, you will be able to mange the index in Pinecone [console](https://app.pinecone.io/). @@ -117,7 +117,7 @@ To learn more about customizing the KnowledgeBase and its inner components, see To insert data into the knowledge base, you can create a list of documents and use the `upsert` method: ```python -from resin.models.data_models import Document +from canopy.models.data_models import Document documents = [Document(id="1", text="U2 are an Irish rock band from Dublin, formed in 1976.", source="https://url.com"), Document(id="2", text="Arctic Monkeys are an English rock band formed in Sheffield in 2002.", source="https://another-url.com", metadata={"my-key": "my-value"})] kb.upsert(documents) @@ -126,7 +126,7 @@ kb.upsert(documents) Now you can query the knowledge base with the `query` method to find the most similar documents to a given text: ```python -from resin.models.query_models import Query +from canopy.models.query_models import Query results = kb.query([Query("Arctic Monkeys music genre"), Query(text="U2 music genre", top_k=10, @@ -146,7 +146,7 @@ The output of the context engine is designed to provide the LLM the most relevan To create a context engine using a knowledge base, you can use the following command: ```python -from resin.context_engine import ContextEngine +from canopy.context_engine import ContextEngine context_engine = ContextEngine(kb) ``` @@ -183,7 +183,7 @@ Given chat history, the chat engine orchestrates its underlying context engine a To create a chat engine using a context, you can use the following command: ```python -from resin.chat_engine import ChatEngine +from canopy.chat_engine import ChatEngine chat_engine = ChatEngine(context_engine) ``` @@ -195,7 +195,7 @@ chat_engine.chat("what is the genre of Arctic Monkeys band?") ``` -Resin designed to be production ready and handle any conversation length and context length. Therefore, the chat engine uses internal components to handle long conversations and long contexts. +Canopy designed to be production ready and handle any conversation length and context length. Therefore, the chat engine uses internal components to handle long conversations and long contexts. By default, long chat history is truncated to the latest messages that fits the token budget. It orchestrates the context engine to retrieve context that fits the token budget and then use the LLM to generate the next response. diff --git a/pyproject.toml b/pyproject.toml index 25e282f4..77187023 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,12 @@ [tool.poetry] -name = "pinecone-resin" +name = "pinecone-canopy" version = "0.1.0" -description = "Resin is an orchestration engine for intergating LLMs with Pinecone." +description = "Canopy is an orchestration engine for intergating LLMs with Pinecone." authors = ["Relevance Team "] readme = "README.md" -packages = [{include = "resin", from = "src"}, - {include = "resin_cli", from = "src"},] - +license = "Apache-2.0" +packages = [{include = "canopy", from = "src"}, + {include = "canopy_cli", from = "src"},] [tool.poetry.dependencies] python = "^3.9" @@ -68,5 +68,4 @@ exclude = ['.venv'] max-line-length = 88 [tool.poetry.scripts] -resin = "resin_cli.cli:cli" -service = "resin_cli.service.app:start" +canopy = "canopy_cli.cli:cli" diff --git a/src/resin/__init__.py b/src/canopy/__init__.py similarity index 56% rename from src/resin/__init__.py rename to src/canopy/__init__.py index 4a604304..95876e09 100644 --- a/src/resin/__init__.py +++ b/src/canopy/__init__.py @@ -1,4 +1,4 @@ import importlib.metadata # Taken from https://stackoverflow.com/a/67097076 -__version__ = importlib.metadata.version("pinecone-resin") +__version__ = importlib.metadata.version("pinecone-canopy") diff --git a/src/resin/chat_engine/__init__.py b/src/canopy/chat_engine/__init__.py similarity index 100% rename from src/resin/chat_engine/__init__.py rename to src/canopy/chat_engine/__init__.py diff --git a/src/resin/chat_engine/chat_engine.py b/src/canopy/chat_engine/chat_engine.py similarity index 90% rename from src/resin/chat_engine/chat_engine.py rename to src/canopy/chat_engine/chat_engine.py index f0282322..fd798cd7 100644 --- a/src/resin/chat_engine/chat_engine.py +++ b/src/canopy/chat_engine/chat_engine.py @@ -2,18 +2,18 @@ from abc import ABC, abstractmethod from typing import Iterable, Union, Optional, cast -from resin.chat_engine.models import HistoryPruningMethod -from resin.chat_engine.prompt_builder import PromptBuilder -from resin.chat_engine.query_generator import (QueryGenerator, - FunctionCallingQueryGenerator, ) -from resin.context_engine import ContextEngine -from resin.tokenizer import Tokenizer -from resin.llm import BaseLLM, OpenAILLM -from resin.llm.models import ModelParams, SystemMessage -from resin.models.api_models import (StreamingChatChunk, ChatResponse, - StreamingChatResponse, ) -from resin.models.data_models import Context, Messages -from resin.utils.config import ConfigurableMixin +from canopy.chat_engine.models import HistoryPruningMethod +from canopy.chat_engine.prompt_builder import PromptBuilder +from canopy.chat_engine.query_generator import (QueryGenerator, + FunctionCallingQueryGenerator, ) +from canopy.context_engine import ContextEngine +from canopy.tokenizer import Tokenizer +from canopy.llm import BaseLLM, OpenAILLM +from canopy.llm.models import ModelParams, SystemMessage +from canopy.models.api_models import (StreamingChatChunk, ChatResponse, + StreamingChatResponse, ) +from canopy.models.data_models import Context, Messages +from canopy.utils.config import ConfigurableMixin CE_DEBUG_INFO = os.getenv("CE_DEBUG_INFO", "FALSE").lower() == "true" diff --git a/src/resin/chat_engine/exceptions.py b/src/canopy/chat_engine/exceptions.py similarity index 100% rename from src/resin/chat_engine/exceptions.py rename to src/canopy/chat_engine/exceptions.py diff --git a/src/resin/chat_engine/history_pruner/__init__.py b/src/canopy/chat_engine/history_pruner/__init__.py similarity index 100% rename from src/resin/chat_engine/history_pruner/__init__.py rename to src/canopy/chat_engine/history_pruner/__init__.py diff --git a/src/resin/chat_engine/history_pruner/base.py b/src/canopy/chat_engine/history_pruner/base.py similarity index 87% rename from src/resin/chat_engine/history_pruner/base.py rename to src/canopy/chat_engine/history_pruner/base.py index 7cca421e..12a3dacf 100644 --- a/src/resin/chat_engine/history_pruner/base.py +++ b/src/canopy/chat_engine/history_pruner/base.py @@ -1,8 +1,8 @@ from abc import ABC, abstractmethod from typing import Tuple -from resin.tokenizer import Tokenizer -from resin.models.data_models import Messages +from canopy.tokenizer import Tokenizer +from canopy.models.data_models import Messages class HistoryPruner(ABC): diff --git a/src/resin/chat_engine/history_pruner/raising.py b/src/canopy/chat_engine/history_pruner/raising.py similarity index 86% rename from src/resin/chat_engine/history_pruner/raising.py rename to src/canopy/chat_engine/history_pruner/raising.py index e24efbd8..008bfe36 100644 --- a/src/resin/chat_engine/history_pruner/raising.py +++ b/src/canopy/chat_engine/history_pruner/raising.py @@ -1,7 +1,7 @@ from typing import Tuple -from resin.chat_engine.history_pruner.base import HistoryPruner -from resin.models.data_models import Messages +from canopy.chat_engine.history_pruner.base import HistoryPruner +from canopy.models.data_models import Messages class RaisingHistoryPruner(HistoryPruner): diff --git a/src/resin/chat_engine/history_pruner/recent.py b/src/canopy/chat_engine/history_pruner/recent.py similarity index 92% rename from src/resin/chat_engine/history_pruner/recent.py rename to src/canopy/chat_engine/history_pruner/recent.py index d8d0dd55..7cf5e2b9 100644 --- a/src/resin/chat_engine/history_pruner/recent.py +++ b/src/canopy/chat_engine/history_pruner/recent.py @@ -1,7 +1,7 @@ from typing import Tuple -from resin.chat_engine.history_pruner.base import HistoryPruner -from resin.models.data_models import Messages +from canopy.chat_engine.history_pruner.base import HistoryPruner +from canopy.models.data_models import Messages class RecentHistoryPruner(HistoryPruner): diff --git a/src/resin/chat_engine/models.py b/src/canopy/chat_engine/models.py similarity index 100% rename from src/resin/chat_engine/models.py rename to src/canopy/chat_engine/models.py diff --git a/src/resin/chat_engine/prompt_builder/__init__.py b/src/canopy/chat_engine/prompt_builder/__init__.py similarity index 100% rename from src/resin/chat_engine/prompt_builder/__init__.py rename to src/canopy/chat_engine/prompt_builder/__init__.py diff --git a/src/resin/chat_engine/prompt_builder/prompt_builder.py b/src/canopy/chat_engine/prompt_builder/prompt_builder.py similarity index 83% rename from src/resin/chat_engine/prompt_builder/prompt_builder.py rename to src/canopy/chat_engine/prompt_builder/prompt_builder.py index fc58104c..a9bb3096 100644 --- a/src/resin/chat_engine/prompt_builder/prompt_builder.py +++ b/src/canopy/chat_engine/prompt_builder/prompt_builder.py @@ -1,12 +1,12 @@ from abc import ABC, abstractmethod -from resin.chat_engine.exceptions import InvalidRequestError -from resin.chat_engine.history_pruner import (RaisingHistoryPruner, - RecentHistoryPruner, ) -from resin.chat_engine.history_pruner.base import HistoryPruner -from resin.chat_engine.models import HistoryPruningMethod -from resin.tokenizer import Tokenizer -from resin.models.data_models import Messages, Role, MessageBase +from canopy.chat_engine.exceptions import InvalidRequestError +from canopy.chat_engine.history_pruner import (RaisingHistoryPruner, + RecentHistoryPruner, ) +from canopy.chat_engine.history_pruner.base import HistoryPruner +from canopy.chat_engine.models import HistoryPruningMethod +from canopy.tokenizer import Tokenizer +from canopy.models.data_models import Messages, Role, MessageBase class BasePromptBuilder(ABC): diff --git a/src/resin/chat_engine/query_generator/__init__.py b/src/canopy/chat_engine/query_generator/__init__.py similarity index 100% rename from src/resin/chat_engine/query_generator/__init__.py rename to src/canopy/chat_engine/query_generator/__init__.py diff --git a/src/resin/chat_engine/query_generator/base.py b/src/canopy/chat_engine/query_generator/base.py similarity index 82% rename from src/resin/chat_engine/query_generator/base.py rename to src/canopy/chat_engine/query_generator/base.py index 6305b6cd..4114163d 100644 --- a/src/resin/chat_engine/query_generator/base.py +++ b/src/canopy/chat_engine/query_generator/base.py @@ -1,8 +1,8 @@ from abc import ABC, abstractmethod from typing import List -from resin.models.data_models import Messages, Query -from resin.utils.config import ConfigurableMixin +from canopy.models.data_models import Messages, Query +from canopy.utils.config import ConfigurableMixin class QueryGenerator(ABC, ConfigurableMixin): diff --git a/src/resin/chat_engine/query_generator/function_calling.py b/src/canopy/chat_engine/query_generator/function_calling.py similarity index 85% rename from src/resin/chat_engine/query_generator/function_calling.py rename to src/canopy/chat_engine/query_generator/function_calling.py index b323774c..7fb21577 100644 --- a/src/resin/chat_engine/query_generator/function_calling.py +++ b/src/canopy/chat_engine/query_generator/function_calling.py @@ -1,12 +1,12 @@ from typing import List, Optional -from resin.chat_engine.models import HistoryPruningMethod -from resin.chat_engine.prompt_builder import PromptBuilder -from resin.chat_engine.query_generator import QueryGenerator -from resin.llm import BaseLLM, OpenAILLM -from resin.llm.models import (Function, FunctionParameters, - FunctionArrayProperty) -from resin.models.data_models import Messages, Query +from canopy.chat_engine.models import HistoryPruningMethod +from canopy.chat_engine.prompt_builder import PromptBuilder +from canopy.chat_engine.query_generator import QueryGenerator +from canopy.llm import BaseLLM, OpenAILLM +from canopy.llm.models import (Function, FunctionParameters, + FunctionArrayProperty) +from canopy.models.data_models import Messages, Query DEFAULT_SYSTEM_PROMPT = """Your task is to formulate search queries for a search engine, to assist in responding to the user's question. You should break down complex questions into sub-queries if needed. diff --git a/src/resin/context_engine/__init__.py b/src/canopy/context_engine/__init__.py similarity index 100% rename from src/resin/context_engine/__init__.py rename to src/canopy/context_engine/__init__.py diff --git a/src/resin/context_engine/context_builder/__init__.py b/src/canopy/context_engine/context_builder/__init__.py similarity index 100% rename from src/resin/context_engine/context_builder/__init__.py rename to src/canopy/context_engine/context_builder/__init__.py diff --git a/src/resin/context_engine/context_builder/base.py b/src/canopy/context_engine/context_builder/base.py similarity index 78% rename from src/resin/context_engine/context_builder/base.py rename to src/canopy/context_engine/context_builder/base.py index 84f5283a..7c568068 100644 --- a/src/resin/context_engine/context_builder/base.py +++ b/src/canopy/context_engine/context_builder/base.py @@ -1,9 +1,9 @@ from abc import ABC, abstractmethod from typing import List -from resin.knowledge_base.models import QueryResult -from resin.models.data_models import Context -from resin.utils.config import ConfigurableMixin +from canopy.knowledge_base.models import QueryResult +from canopy.models.data_models import Context +from canopy.utils.config import ConfigurableMixin class ContextBuilder(ABC, ConfigurableMixin): diff --git a/src/resin/context_engine/context_builder/stuffing.py b/src/canopy/context_engine/context_builder/stuffing.py similarity index 89% rename from src/resin/context_engine/context_builder/stuffing.py rename to src/canopy/context_engine/context_builder/stuffing.py index c7ebb70e..18ebc56a 100644 --- a/src/resin/context_engine/context_builder/stuffing.py +++ b/src/canopy/context_engine/context_builder/stuffing.py @@ -1,11 +1,11 @@ from itertools import zip_longest from typing import List, Tuple -from resin.context_engine.context_builder.base import ContextBuilder -from resin.context_engine.models import ContextQueryResult, ContextSnippet -from resin.knowledge_base.models import QueryResult, DocumentWithScore -from resin.tokenizer import Tokenizer -from resin.models.data_models import Context +from canopy.context_engine.context_builder.base import ContextBuilder +from canopy.context_engine.models import ContextQueryResult, ContextSnippet +from canopy.knowledge_base.models import QueryResult, DocumentWithScore +from canopy.tokenizer import Tokenizer +from canopy.models.data_models import Context class StuffingContextBuilder(ContextBuilder): diff --git a/src/resin/context_engine/context_engine.py b/src/canopy/context_engine/context_engine.py similarity index 85% rename from src/resin/context_engine/context_engine.py rename to src/canopy/context_engine/context_engine.py index ae99c46c..9f9f03db 100644 --- a/src/resin/context_engine/context_engine.py +++ b/src/canopy/context_engine/context_engine.py @@ -2,12 +2,12 @@ from abc import ABC, abstractmethod from typing import List, Optional -from resin.context_engine.context_builder import StuffingContextBuilder -from resin.context_engine.context_builder.base import ContextBuilder -from resin.knowledge_base import KnowledgeBase -from resin.knowledge_base.base import BaseKnowledgeBase -from resin.models.data_models import Context, Query -from resin.utils.config import ConfigurableMixin +from canopy.context_engine.context_builder import StuffingContextBuilder +from canopy.context_engine.context_builder.base import ContextBuilder +from canopy.knowledge_base import KnowledgeBase +from canopy.knowledge_base.base import BaseKnowledgeBase +from canopy.models.data_models import Context, Query +from canopy.utils.config import ConfigurableMixin CE_DEBUG_INFO = os.getenv("CE_DEBUG_INFO", "FALSE").lower() == "true" diff --git a/src/resin/context_engine/models.py b/src/canopy/context_engine/models.py similarity index 83% rename from src/resin/context_engine/models.py rename to src/canopy/context_engine/models.py index df115c41..b5b14f1e 100644 --- a/src/resin/context_engine/models.py +++ b/src/canopy/context_engine/models.py @@ -2,7 +2,7 @@ from pydantic import BaseModel -from resin.models.data_models import ContextContent +from canopy.models.data_models import ContextContent class ContextSnippet(BaseModel): diff --git a/src/resin/knowledge_base/__init__.py b/src/canopy/knowledge_base/__init__.py similarity index 100% rename from src/resin/knowledge_base/__init__.py rename to src/canopy/knowledge_base/__init__.py diff --git a/src/resin/knowledge_base/base.py b/src/canopy/knowledge_base/base.py similarity index 89% rename from src/resin/knowledge_base/base.py rename to src/canopy/knowledge_base/base.py index f639b8a5..9bf6278c 100644 --- a/src/resin/knowledge_base/base.py +++ b/src/canopy/knowledge_base/base.py @@ -1,9 +1,9 @@ from abc import ABC, abstractmethod from typing import List, Optional -from resin.knowledge_base.models import QueryResult -from resin.models.data_models import Query, Document -from resin.utils.config import ConfigurableMixin +from canopy.knowledge_base.models import QueryResult +from canopy.models.data_models import Query, Document +from canopy.utils.config import ConfigurableMixin class BaseKnowledgeBase(ABC, ConfigurableMixin): diff --git a/src/resin/knowledge_base/chunker/__init__.py b/src/canopy/knowledge_base/chunker/__init__.py similarity index 100% rename from src/resin/knowledge_base/chunker/__init__.py rename to src/canopy/knowledge_base/chunker/__init__.py diff --git a/src/resin/knowledge_base/chunker/base.py b/src/canopy/knowledge_base/chunker/base.py similarity index 86% rename from src/resin/knowledge_base/chunker/base.py rename to src/canopy/knowledge_base/chunker/base.py index a375073d..1816cfc3 100644 --- a/src/resin/knowledge_base/chunker/base.py +++ b/src/canopy/knowledge_base/chunker/base.py @@ -1,9 +1,9 @@ from abc import ABC, abstractmethod from typing import List -from resin.knowledge_base.models import KBDocChunk -from resin.models.data_models import Document -from resin.utils.config import ConfigurableMixin +from canopy.knowledge_base.models import KBDocChunk +from canopy.models.data_models import Document +from canopy.utils.config import ConfigurableMixin class Chunker(ABC, ConfigurableMixin): diff --git a/src/resin/knowledge_base/chunker/langchain_text_splitter.py b/src/canopy/knowledge_base/chunker/langchain_text_splitter.py similarity index 100% rename from src/resin/knowledge_base/chunker/langchain_text_splitter.py rename to src/canopy/knowledge_base/chunker/langchain_text_splitter.py diff --git a/src/resin/knowledge_base/chunker/markdown.py b/src/canopy/knowledge_base/chunker/markdown.py similarity index 89% rename from src/resin/knowledge_base/chunker/markdown.py rename to src/canopy/knowledge_base/chunker/markdown.py index ad8976c3..cf1ef1e9 100644 --- a/src/resin/knowledge_base/chunker/markdown.py +++ b/src/canopy/knowledge_base/chunker/markdown.py @@ -2,8 +2,8 @@ from .langchain_text_splitter import Language, RecursiveCharacterTextSplitter from .recursive_character import RecursiveCharacterChunker -from resin.knowledge_base.models import KBDocChunk -from resin.models.data_models import Document +from canopy.knowledge_base.models import KBDocChunk +from canopy.models.data_models import Document class MarkdownChunker(RecursiveCharacterChunker): diff --git a/src/resin/knowledge_base/chunker/recursive_character.py b/src/canopy/knowledge_base/chunker/recursive_character.py similarity index 87% rename from src/resin/knowledge_base/chunker/recursive_character.py rename to src/canopy/knowledge_base/chunker/recursive_character.py index 73651fd0..f978c944 100644 --- a/src/resin/knowledge_base/chunker/recursive_character.py +++ b/src/canopy/knowledge_base/chunker/recursive_character.py @@ -3,10 +3,10 @@ from .langchain_text_splitter import RecursiveCharacterTextSplitter -from resin.knowledge_base.chunker.base import Chunker -from resin.knowledge_base.models import KBDocChunk -from resin.tokenizer import Tokenizer -from resin.models.data_models import Document +from canopy.knowledge_base.chunker.base import Chunker +from canopy.knowledge_base.models import KBDocChunk +from canopy.tokenizer import Tokenizer +from canopy.models.data_models import Document class RecursiveCharacterChunker(Chunker): diff --git a/src/resin/knowledge_base/chunker/token_chunker.py b/src/canopy/knowledge_base/chunker/token_chunker.py similarity index 97% rename from src/resin/knowledge_base/chunker/token_chunker.py rename to src/canopy/knowledge_base/chunker/token_chunker.py index ce1494bd..d143b806 100644 --- a/src/resin/knowledge_base/chunker/token_chunker.py +++ b/src/canopy/knowledge_base/chunker/token_chunker.py @@ -2,7 +2,7 @@ from .base import Chunker from ..models import KBDocChunk -from resin.tokenizer import Tokenizer +from canopy.tokenizer import Tokenizer from ...models.data_models import Document diff --git a/src/resin/knowledge_base/knowledge_base.py b/src/canopy/knowledge_base/knowledge_base.py similarity index 90% rename from src/resin/knowledge_base/knowledge_base.py rename to src/canopy/knowledge_base/knowledge_base.py index 13a2f76c..4d0c5ae2 100644 --- a/src/resin/knowledge_base/knowledge_base.py +++ b/src/canopy/knowledge_base/knowledge_base.py @@ -16,17 +16,17 @@ from pinecone_datasets import Dataset from pinecone_datasets import DenseModelMetadata, DatasetMetadata -from resin.knowledge_base.base import BaseKnowledgeBase -from resin.knowledge_base.chunker import Chunker, MarkdownChunker -from resin.knowledge_base.record_encoder import (RecordEncoder, - OpenAIRecordEncoder) -from resin.knowledge_base.models import (KBQueryResult, KBQuery, QueryResult, - KBDocChunkWithScore, DocumentWithScore) -from resin.knowledge_base.reranker import Reranker, TransparentReranker -from resin.models.data_models import Query, Document +from canopy.knowledge_base.base import BaseKnowledgeBase +from canopy.knowledge_base.chunker import Chunker, MarkdownChunker +from canopy.knowledge_base.record_encoder import (RecordEncoder, + OpenAIRecordEncoder) +from canopy.knowledge_base.models import (KBQueryResult, KBQuery, QueryResult, + KBDocChunkWithScore, DocumentWithScore) +from canopy.knowledge_base.reranker import Reranker, TransparentReranker +from canopy.models.data_models import Query, Document -INDEX_NAME_PREFIX = "resin--" +INDEX_NAME_PREFIX = "canopy--" TIMEOUT_INDEX_CREATE = 300 TIMEOUT_INDEX_PROVISION = 30 INDEX_PROVISION_TIME_INTERVAL = 3 @@ -46,18 +46,18 @@ class KnowledgeBase(BaseKnowledgeBase): After documents were inserted, the KnowledgeBase can be queried by sending a textual query, which will first encoded to a vector and then used to retrieve the closest top-k document chunks. - Note: Since Resin defines its own data format, you can not use a pre-existing Pinecone index with Resin's KnowledgeBase. - The index must be created by using `knowledge_base.create_resin_index()` or the CLI command `resin new`. + Note: Since Canopy defines its own data format, you can not use a pre-existing Pinecone index with Canopy's KnowledgeBase. + The index must be created by using `knowledge_base.create_canopy_index()` or the CLI command `canopy new`. - When creating a new Resin service, the user must first create the underlying Pinecone index. + When creating a new Canopy service, the user must first create the underlying Pinecone index. This is a one-time setup process - the index will exist on Pinecone's managed service until it is deleted. Example: - >>> from resin.knowledge_base.knowledge_base import KnowledgeBase + >>> from canopy.knowledge_base.knowledge_base import KnowledgeBase >>> from tokenizer import Tokenizer >>> Tokenizer.initialize() >>> kb = KnowledgeBase(index_name="my_index") - >>> kb.create_resin_index() + >>> kb.create_canopy_index() In any future interactions, the user simply needs to connect to the existing index: @@ -82,19 +82,19 @@ def __init__(self, """ Initilize the knowledge base object. - If the index does not exist, the user must first create it by calling `create_resin_index()` or the CLI command `resin new`. + If the index does not exist, the user must first create it by calling `create_canopy_index()` or the CLI command `canopy new`. - Note: Resin will add the prefix --resin to your selected index name. + Note: Canopy will add the prefix --canopy to your selected index name. You can retrieve the full index name knowledge_base.index_name at any time, or find it in the Pinecone console at https://app.pinecone.io/ Example: create a new index: - >>> from resin.knowledge_base.knowledge_base import KnowledgeBase + >>> from canopy.knowledge_base.knowledge_base import KnowledgeBase >>> from tokenizer import Tokenizer >>> Tokenizer.initialize() >>> kb = KnowledgeBase(index_name="my_index") - >>> kb.create_resin_index() + >>> kb.create_canopy_index() In any future interactions, the user simply needs to connect to the existing index: @@ -149,13 +149,13 @@ def __init__(self, else: self._reranker = self._DEFAULT_COMPONENTS['reranker']() - # Normally, index creation params are passed directly to the `.create_resin_index()` method. # noqa: E501 + # Normally, index creation params are passed directly to the `.create_canopy_index()` method. # noqa: E501 # However, when KnowledgeBase is initialized from a config file, these params # would be set by the `KnowledgeBase.from_config()` constructor. self._index_params: Dict[str, Any] = {} # The index object is initialized lazily, when the user calls `connect()` or - # `create_resin_index()` + # `create_canopy_index()` self._index: Optional[Index] = None @staticmethod @@ -176,8 +176,8 @@ def _connect_index(self, if self.index_name not in list_indexes(): raise RuntimeError( f"The index {self.index_name} does not exist or was deleted. " - "Please create it by calling knowledge_base.create_resin_index() or " - "running the `resin new` command" + "Please create it by calling knowledge_base.create_canopy_index() or " + "running the `canopy new` command" ) try: @@ -203,7 +203,7 @@ def connect(self) -> None: This method must be called before making any other calls to the knowledge base. Note: If underlying index is not provisioned yet, an exception will be raised. - To provision the index, use `create_resin_index()` or the CLI command `resin new`. + To provision the index, use `create_canopy_index()` or the CLI command `canopy new`. Returns: None @@ -234,24 +234,24 @@ def verify_index_connection(self) -> None: "The index did not respond. Please check your credentials and try again" ) from e - def create_resin_index(self, - indexed_fields: Optional[List[str]] = None, - dimension: Optional[int] = None, - index_params: Optional[dict] = None - ): + def create_canopy_index(self, + indexed_fields: Optional[List[str]] = None, + dimension: Optional[int] = None, + index_params: Optional[dict] = None + ): """ Creates the underlying Pinecone index that will be used by the KnowledgeBase. - This is a one time set-up operation that only needs to be done once for every new Resin service. + This is a one time set-up operation that only needs to be done once for every new Canopy service. After the index was created, it will persist in Pinecone until explicitly deleted. - Since Resin defines its own data format, namely a few dedicated metadata fields, - you can not use a pre-existing Pinecone index with Resin's KnowledgeBase. - The index must be created by using `knowledge_base.create_resin_index()` or the CLI command `resin new`. + Since Canopy defines its own data format, namely a few dedicated metadata fields, + you can not use a pre-existing Pinecone index with Canopy's KnowledgeBase. + The index must be created by using `knowledge_base.create_canopy_index()` or the CLI command `canopy new`. Note: This operation may take a few minutes to complete. Once created, you can see the index in the Pinecone console - Note: Resin will add the prefix --resin to your selected index name. + Note: Canopy will add the prefix --canopy to your selected index name. You can retrieve the full index name knowledge_base.index_name at any time. Or find it in the Pinecone console at https://app.pinecone.io/ @@ -260,11 +260,11 @@ def create_resin_index(self, allowing them to be later used for metadata filtering. All other metadata fields are stored but not indexed. See: https://docs.pinecone.io/docs/manage-indexes#selective-metadata-indexing. - Resin always indexes a built-in `document_id` field, which is added to every vector. + Canopy always indexes a built-in `document_id` field, which is added to every vector. By default - all other metadata fields are **not** indexed, unless explicitly defined in this list. dimension: The dimension of the vectors to index. If `dimension` isn't explicitly provided, - Resin would try to infer the embedding's dimension based on the configured `Encoder` + Canopy would try to infer the embedding's dimension based on the configured `Encoder` index_params: A dictionary of parameters to pass to the index creation API. For example, you can set the index's number of replicas by passing {"replicas": 2}. see https://docs.pinecone.io/docs/python-client#create_index @@ -365,8 +365,8 @@ def delete_index(self): After deletion - the `KnowledgeBase` would not be connected to a Pinecone index anymore, so you will not be able to insert documents or query. - If you'd wish to re-create an index with the same name, simply call `knowledge_base.create_resin_index()` - Or use the CLI command `resin new`. + If you'd wish to re-create an index with the same name, simply call `knowledge_base.create_canopy_index()` + Or use the CLI command `canopy new`. """ # noqa: E501 if self._index is None: raise RuntimeError(self._connection_error_msg) @@ -395,7 +395,7 @@ def query(self, A list of QueryResult objects. Examples: - >>> from resin.knowledge_base.knowledge_base import KnowledgeBase + >>> from canopy.knowledge_base.knowledge_base import KnowledgeBase >>> from tokenizer import Tokenizer >>> Tokenizer.initialize() >>> kb = KnowledgeBase(index_name="my_index") @@ -494,7 +494,7 @@ def upsert(self, None Example: - >>> from resin.knowledge_base.knowledge_base import KnowledgeBase + >>> from canopy.knowledge_base.knowledge_base import KnowledgeBase >>> from tokenizer import Tokenizer >>> Tokenizer.initialize() >>> kb = KnowledgeBase(index_name="my_index") @@ -573,7 +573,7 @@ def delete(self, None Example: - >>> from resin.knowledge_base.knowledge_base import KnowledgeBase + >>> from canopy.knowledge_base.knowledge_base import KnowledgeBase >>> from tokenizer import Tokenizer >>> Tokenizer.initialize() >>> kb = KnowledgeBase(index_name="my_index") diff --git a/src/resin/knowledge_base/models.py b/src/canopy/knowledge_base/models.py similarity index 96% rename from src/resin/knowledge_base/models.py rename to src/canopy/knowledge_base/models.py index 50bcbac4..28f3aa18 100644 --- a/src/resin/knowledge_base/models.py +++ b/src/canopy/knowledge_base/models.py @@ -4,7 +4,7 @@ from pinecone_text.sparse import SparseVector from pydantic import BaseModel, Field -from resin.models.data_models import Document, Query +from canopy.models.data_models import Document, Query # TODO 1: consider moving this to pinecone-text # TODO 2: consider renaming to "Vector" or "DenseVector" diff --git a/src/resin/knowledge_base/record_encoder/__init__.py b/src/canopy/knowledge_base/record_encoder/__init__.py similarity index 100% rename from src/resin/knowledge_base/record_encoder/__init__.py rename to src/canopy/knowledge_base/record_encoder/__init__.py diff --git a/src/resin/knowledge_base/record_encoder/base.py b/src/canopy/knowledge_base/record_encoder/base.py similarity index 93% rename from src/resin/knowledge_base/record_encoder/base.py rename to src/canopy/knowledge_base/record_encoder/base.py index 47284781..c49f42da 100644 --- a/src/resin/knowledge_base/record_encoder/base.py +++ b/src/canopy/knowledge_base/record_encoder/base.py @@ -1,9 +1,9 @@ from abc import ABC, abstractmethod from typing import List, Optional -from resin.knowledge_base.models import KBEncodedDocChunk, KBQuery, KBDocChunk -from resin.models.data_models import Query -from resin.utils.config import ConfigurableMixin +from canopy.knowledge_base.models import KBEncodedDocChunk, KBQuery, KBDocChunk +from canopy.models.data_models import Query +from canopy.utils.config import ConfigurableMixin class RecordEncoder(ABC, ConfigurableMixin): diff --git a/src/resin/knowledge_base/record_encoder/dense.py b/src/canopy/knowledge_base/record_encoder/dense.py similarity index 92% rename from src/resin/knowledge_base/record_encoder/dense.py rename to src/canopy/knowledge_base/record_encoder/dense.py index 8db12001..730288c3 100644 --- a/src/resin/knowledge_base/record_encoder/dense.py +++ b/src/canopy/knowledge_base/record_encoder/dense.py @@ -3,8 +3,8 @@ from pinecone_text.dense.base_dense_ecoder import BaseDenseEncoder from .base import RecordEncoder -from resin.knowledge_base.models import KBQuery, KBEncodedDocChunk, KBDocChunk -from resin.models.data_models import Query +from canopy.knowledge_base.models import KBQuery, KBEncodedDocChunk, KBDocChunk +from canopy.models.data_models import Query class DenseRecordEncoder(RecordEncoder): diff --git a/src/resin/knowledge_base/record_encoder/openai.py b/src/canopy/knowledge_base/record_encoder/openai.py similarity index 81% rename from src/resin/knowledge_base/record_encoder/openai.py rename to src/canopy/knowledge_base/record_encoder/openai.py index b56cb743..3a1ec728 100644 --- a/src/resin/knowledge_base/record_encoder/openai.py +++ b/src/canopy/knowledge_base/record_encoder/openai.py @@ -6,10 +6,10 @@ retry_if_exception_type, ) from pinecone_text.dense.openai_encoder import OpenAIEncoder -from resin.knowledge_base.models import KBDocChunk, KBEncodedDocChunk, KBQuery -from resin.knowledge_base.record_encoder.dense import DenseRecordEncoder -from resin.models.data_models import Query -from resin.utils.openai_exceptions import OPEN_AI_TRANSIENT_EXCEPTIONS +from canopy.knowledge_base.models import KBDocChunk, KBEncodedDocChunk, KBQuery +from canopy.knowledge_base.record_encoder.dense import DenseRecordEncoder +from canopy.models.data_models import Query +from canopy.utils.openai_exceptions import OPEN_AI_TRANSIENT_EXCEPTIONS class OpenAIRecordEncoder(DenseRecordEncoder): diff --git a/src/resin/knowledge_base/reranker/__init__.py b/src/canopy/knowledge_base/reranker/__init__.py similarity index 100% rename from src/resin/knowledge_base/reranker/__init__.py rename to src/canopy/knowledge_base/reranker/__init__.py diff --git a/src/resin/knowledge_base/reranker/reranker.py b/src/canopy/knowledge_base/reranker/reranker.py similarity index 84% rename from src/resin/knowledge_base/reranker/reranker.py rename to src/canopy/knowledge_base/reranker/reranker.py index 04fe9f1f..7731141a 100644 --- a/src/resin/knowledge_base/reranker/reranker.py +++ b/src/canopy/knowledge_base/reranker/reranker.py @@ -1,8 +1,8 @@ from abc import ABC, abstractmethod from typing import List -from resin.knowledge_base.models import KBQueryResult -from resin.utils.config import ConfigurableMixin +from canopy.knowledge_base.models import KBQueryResult +from canopy.utils.config import ConfigurableMixin class Reranker(ABC, ConfigurableMixin): diff --git a/src/resin/llm/__init__.py b/src/canopy/llm/__init__.py similarity index 100% rename from src/resin/llm/__init__.py rename to src/canopy/llm/__init__.py diff --git a/src/resin/llm/base.py b/src/canopy/llm/base.py similarity index 90% rename from src/resin/llm/base.py rename to src/canopy/llm/base.py index 5b5f6ddb..f66f6c0c 100644 --- a/src/resin/llm/base.py +++ b/src/canopy/llm/base.py @@ -1,10 +1,10 @@ from abc import ABC, abstractmethod from typing import Union, Iterable, Optional, List -from resin.llm.models import Function, ModelParams -from resin.models.api_models import ChatResponse, StreamingChatChunk -from resin.models.data_models import Messages, Query -from resin.utils.config import ConfigurableMixin +from canopy.llm.models import Function, ModelParams +from canopy.models.api_models import ChatResponse, StreamingChatChunk +from canopy.models.data_models import Messages, Query +from canopy.utils.config import ConfigurableMixin class BaseLLM(ABC, ConfigurableMixin): diff --git a/src/resin/llm/models.py b/src/canopy/llm/models.py similarity index 96% rename from src/resin/llm/models.py rename to src/canopy/llm/models.py index c6469ce3..3c198688 100644 --- a/src/resin/llm/models.py +++ b/src/canopy/llm/models.py @@ -2,7 +2,7 @@ from pydantic import BaseModel -from resin.models.data_models import MessageBase, Role +from canopy.models.data_models import MessageBase, Role class UserMessage(MessageBase): diff --git a/src/resin/llm/openai.py b/src/canopy/llm/openai.py similarity index 93% rename from src/resin/llm/openai.py rename to src/canopy/llm/openai.py index 9e43fb6e..812fc5e0 100644 --- a/src/resin/llm/openai.py +++ b/src/canopy/llm/openai.py @@ -8,11 +8,11 @@ stop_after_attempt, retry_if_exception_type, ) -from resin.utils.openai_exceptions import OPEN_AI_TRANSIENT_EXCEPTIONS -from resin.llm import BaseLLM -from resin.llm.models import Function, ModelParams -from resin.models.api_models import ChatResponse, StreamingChatChunk -from resin.models.data_models import Messages, Query +from canopy.utils.openai_exceptions import OPEN_AI_TRANSIENT_EXCEPTIONS +from canopy.llm import BaseLLM +from canopy.llm.models import Function, ModelParams +from canopy.models.api_models import ChatResponse, StreamingChatChunk +from canopy.models.data_models import Messages, Query class OpenAILLM(BaseLLM): diff --git a/src/resin/models/__init__.py b/src/canopy/models/__init__.py similarity index 100% rename from src/resin/models/__init__.py rename to src/canopy/models/__init__.py diff --git a/src/resin/models/api_models.py b/src/canopy/models/api_models.py similarity index 95% rename from src/resin/models/api_models.py rename to src/canopy/models/api_models.py index a21c4994..964aa48d 100644 --- a/src/resin/models/api_models.py +++ b/src/canopy/models/api_models.py @@ -2,7 +2,7 @@ from pydantic import BaseModel, Field, validator -from resin.models.data_models import MessageBase +from canopy.models.data_models import MessageBase class _Choice(BaseModel): diff --git a/src/resin/models/data_models.py b/src/canopy/models/data_models.py similarity index 100% rename from src/resin/models/data_models.py rename to src/canopy/models/data_models.py diff --git a/src/resin/tokenizer/__init__.py b/src/canopy/tokenizer/__init__.py similarity index 100% rename from src/resin/tokenizer/__init__.py rename to src/canopy/tokenizer/__init__.py diff --git a/src/resin/tokenizer/base.py b/src/canopy/tokenizer/base.py similarity index 82% rename from src/resin/tokenizer/base.py rename to src/canopy/tokenizer/base.py index de6df56a..b668da61 100644 --- a/src/resin/tokenizer/base.py +++ b/src/canopy/tokenizer/base.py @@ -1,8 +1,8 @@ from abc import ABC, abstractmethod from typing import List -from resin.models.data_models import Messages -from resin.utils.config import ConfigurableMixin +from canopy.models.data_models import Messages +from canopy.utils.config import ConfigurableMixin class BaseTokenizer(ABC, ConfigurableMixin): diff --git a/src/resin/tokenizer/openai.py b/src/canopy/tokenizer/openai.py similarity index 100% rename from src/resin/tokenizer/openai.py rename to src/canopy/tokenizer/openai.py diff --git a/src/resin/tokenizer/tokenizer.py b/src/canopy/tokenizer/tokenizer.py similarity index 100% rename from src/resin/tokenizer/tokenizer.py rename to src/canopy/tokenizer/tokenizer.py diff --git a/src/resin/utils/__init__.py b/src/canopy/utils/__init__.py similarity index 100% rename from src/resin/utils/__init__.py rename to src/canopy/utils/__init__.py diff --git a/src/resin/utils/config.py b/src/canopy/utils/config.py similarity index 100% rename from src/resin/utils/config.py rename to src/canopy/utils/config.py diff --git a/src/resin/utils/openai_exceptions.py b/src/canopy/utils/openai_exceptions.py similarity index 100% rename from src/resin/utils/openai_exceptions.py rename to src/canopy/utils/openai_exceptions.py diff --git a/src/resin_cli/__init__.py b/src/canopy_cli/__init__.py similarity index 100% rename from src/resin_cli/__init__.py rename to src/canopy_cli/__init__.py diff --git a/src/resin_cli/api_models.py b/src/canopy_cli/api_models.py similarity index 92% rename from src/resin_cli/api_models.py rename to src/canopy_cli/api_models.py index e94060d7..98ddb799 100644 --- a/src/resin_cli/api_models.py +++ b/src/canopy_cli/api_models.py @@ -2,7 +2,7 @@ from pydantic import BaseModel -from resin.models.data_models import Messages, Query, Document +from canopy.models.data_models import Messages, Query, Document class ChatRequest(BaseModel): diff --git a/src/resin_cli/app.py b/src/canopy_cli/app.py similarity index 90% rename from src/resin_cli/app.py rename to src/canopy_cli/app.py index 765e3070..c2f54903 100644 --- a/src/resin_cli/app.py +++ b/src/canopy_cli/app.py @@ -10,12 +10,12 @@ import yaml from dotenv import load_dotenv -from resin.llm import BaseLLM -from resin.llm.models import UserMessage -from resin.tokenizer import Tokenizer -from resin.knowledge_base import KnowledgeBase -from resin.context_engine import ContextEngine -from resin.chat_engine import ChatEngine +from canopy.llm import BaseLLM +from canopy.llm.models import UserMessage +from canopy.tokenizer import Tokenizer +from canopy.knowledge_base import KnowledgeBase +from canopy.context_engine import ContextEngine +from canopy.chat_engine import ChatEngine from starlette.concurrency import run_in_threadpool from sse_starlette.sse import EventSourceResponse @@ -23,14 +23,14 @@ import uvicorn from typing import cast -from resin.models.api_models import StreamingChatResponse, ChatResponse -from resin.models.data_models import Context -from resin_cli.api_models import \ +from canopy.models.api_models import StreamingChatResponse, ChatResponse +from canopy.models.data_models import Context +from canopy_cli.api_models import \ ChatRequest, ContextQueryRequest, \ ContextUpsertRequest, HealthStatus, ContextDeleteRequest -from resin.llm.openai import OpenAILLM -from resin_cli.errors import ConfigError +from canopy.llm.openai import OpenAILLM +from canopy_cli.errors import ConfigError load_dotenv() # load env vars before import of openai openai.api_key = os.getenv("OPENAI_API_KEY") @@ -186,7 +186,7 @@ def _init_logging(): global logger file_handler = logging.FileHandler( - filename=os.getenv("CE_LOG_FILENAME", "resin.log") + filename=os.getenv("CE_LOG_FILENAME", "canopy.log") ) stdout_handler = logging.StreamHandler(stream=sys.stdout) handlers = [file_handler, stdout_handler] @@ -207,7 +207,7 @@ def _init_engines(): if not index_name: raise ValueError("INDEX_NAME environment variable must be set") - config_file = os.getenv("RESIN_CONFIG_FILE") + config_file = os.getenv("CANOPY_CONFIG_FILE") if config_file: _load_config(config_file) @@ -258,9 +258,9 @@ def _load_config(config_file): def start(host="0.0.0.0", port=8000, reload=False, config_file=None): if config_file: - os.environ["RESIN_CONFIG_FILE"] = config_file + os.environ["CANOPY_CONFIG_FILE"] = config_file - uvicorn.run("resin_cli.app:app", host=host, port=port, reload=reload, workers=0) + uvicorn.run("canopy_cli.app:app", host=host, port=port, reload=reload, workers=0) if __name__ == "__main__": diff --git a/src/resin_cli/cli.py b/src/canopy_cli/cli.py similarity index 86% rename from src/resin_cli/cli.py rename to src/canopy_cli/cli.py index e99f9bf2..c590a5a5 100644 --- a/src/resin_cli/cli.py +++ b/src/canopy_cli/cli.py @@ -17,16 +17,16 @@ from openai.error import APIError as OpenAI_APIError from urllib.parse import urljoin -from resin.knowledge_base import KnowledgeBase -from resin.models.data_models import Document -from resin.tokenizer import Tokenizer -from resin_cli.data_loader import ( +from canopy.knowledge_base import KnowledgeBase +from canopy.models.data_models import Document +from canopy.tokenizer import Tokenizer +from canopy_cli.data_loader import ( load_from_path, IDsNotUniqueError, DocumentsValidationError) -from resin_cli.errors import CLIError +from canopy_cli.errors import CLIError -from resin import __version__ +from canopy import __version__ from .app import start as start_service from .cli_spinner import Spinner @@ -48,8 +48,8 @@ def check_service_health(url: str): return res.ok except requests.exceptions.ConnectionError: msg = f""" - Resin service is not running on {url}. - please run `resin start` + Canopy service is not running on {url}. + please run `canopy start` """ raise CLIError(msg) @@ -59,7 +59,7 @@ def check_service_health(url: str): else: error = str(e) msg = ( - f"Resin service on {url} is not healthy, failed with error: {error}" + f"Canopy service on {url} is not healthy, failed with error: {error}" ) raise CLIError(msg) @@ -89,7 +89,7 @@ def validate_connection(): "Please visit https://platform.openai.com/account/api-keys for more details" ) raise CLIError(msg) - click.echo("Resin: ", nl=False) + click.echo("Canopy: ", nl=False) click.echo(click.style("Ready\n", bold=True, fg="green")) @@ -130,12 +130,12 @@ def _load_kb_config(config_file: Optional[str]) -> Dict[str, Any]: @click.group(invoke_without_command=True, context_settings=CONTEXT_SETTINGS) -@click.version_option(__version__, "-v", "--version", prog_name="Resin") +@click.version_option(__version__, "-v", "--version", prog_name="Canopy") @click.pass_context def cli(ctx): """ \b - CLI for Pinecone Resin. Actively developed by Pinecone. + CLI for Pinecone Canopy. Actively developed by Pinecone. To use the CLI, you need to have a Pinecone account. Visit https://www.pinecone.io/ to sign up for free. """ @@ -145,20 +145,20 @@ def cli(ctx): # click.echo(command.get_help(ctx)) -@cli.command(help="Check if resin service is running and healthy.") +@cli.command(help="Check if canopy service is running and healthy.") @click.option("--url", default="http://0.0.0.0:8000", - help="Resin's service url. Defaults to http://0.0.0.0:8000") + help="Canopy's service url. Defaults to http://0.0.0.0:8000") def health(url): check_service_health(url) - click.echo(click.style("Resin service is healthy!", fg="green")) + click.echo(click.style("Canopy service is healthy!", fg="green")) return @cli.command( help=( - """Create a new Pinecone index that that will be used by Resin. + """Create a new Pinecone index that that will be used by Canopy. \b - A Resin service can not be started without a Pinecone index which is configured to work with Resin. + A Canopy service can not be started without a Pinecone index which is configured to work with Canopy. This command will create a new Pinecone index and configure it in the right schema. If the embedding vectors' dimension is not explicitly configured in @@ -169,18 +169,18 @@ def health(url): ) @click.argument("index-name", nargs=1, envvar="INDEX_NAME", type=str, required=True) @click.option("--config", "-c", default=None, - help="Path to a resin config file. Optional, otherwise configuration " + help="Path to a canopy config file. Optional, otherwise configuration " "defaults will be used.") def new(index_name: str, config: Optional[str]): _initialize_tokenizer() kb_config = _load_kb_config(config) kb = KnowledgeBase.from_config(kb_config, index_name=index_name) - click.echo("Resin is going to create a new index: ", nl=False) + click.echo("Canopy is going to create a new index: ", nl=False) click.echo(click.style(f"{kb.index_name}", fg="green")) click.confirm(click.style("Do you want to continue?", fg="red"), abort=True) with spinner: try: - kb.create_resin_index() + kb.create_canopy_index() # TODO: kb should throw a specific exception for each case except Exception as e: msg = f"Failed to create a new index. Reason:\n{e}" @@ -193,7 +193,7 @@ def new(index_name: str, config: Optional[str]): help=( """ \b - Upload local data files containing documents to the Resin service. + Upload local data files containing documents to the Canopy service. Load all the documents from data file or a directory containing multiple data files. The allowed formats are .jsonl and .parquet. @@ -215,7 +215,7 @@ def new(index_name: str, config: Optional[str]): "When set to True, the upsert process will continue on failure, as " "long as less than 10% of the documents have failed to be uploaded.") @click.option("--config", "-c", default=None, - help="Path to a resin config file. Optional, otherwise configuration " + help="Path to a canopy config file. Optional, otherwise configuration " "defaults will be used.") def upsert(index_name: str, data_path: str, @@ -244,7 +244,7 @@ def upsert(index_name: str, "https://www.pinecone.io/docs/quick-start/ for more details.") raise CLIError(msg) - click.echo("Resin is going to upsert data from ", nl=False) + click.echo("Canopy is going to upsert data from ", nl=False) click.echo(click.style(f'{data_path}', fg='yellow'), nl=False) click.echo(" to index: ") click.echo(click.style(f'{kb.index_name} \n', fg='green')) @@ -297,6 +297,7 @@ def upsert(index_name: str, raise CLIError(msg) pbar.update(len(batch)) + pbar.close() if failed_docs: msg = ( @@ -369,9 +370,9 @@ def _chat( @cli.command( help=( """ - Debugging tool for chatting with the Resin RAG service. + Debugging tool for chatting with the Canopy RAG service. - Run an interactive chat with the Resin RAG service, for debugging and demo + Run an interactive chat with the Canopy RAG service, for debugging and demo purposes. A prompt is provided for the user to enter a message, and the RAG-infused ChatBot will respond. You can continue the conversation by entering more messages. Hit Ctrl+C to exit. @@ -389,7 +390,7 @@ def _chat( @click.option("--baseline/--no-baseline", default=False, help="Compare RAG-infused Chatbot with baseline LLM",) @click.option("--chat-service-url", default="http://0.0.0.0:8000", - help="URL of the Resin service to use. Defaults to http://0.0.0.0:8000") + help="URL of the Canopy service to use. Defaults to http://0.0.0.0:8000") def chat(chat_service_url, baseline, debug, stream): check_service_health(chat_service_url) note_msg = ( @@ -403,7 +404,7 @@ def chat(chat_service_url, baseline, debug, stream): note_white_message = ( "This method should be used by developers to test the RAG data and model" "during development. " - "When you are ready to deploy, run the Resin service as a REST API " + "When you are ready to deploy, run the Canopy service as a REST API " "backend for your chatbot UI. \n\n" "Let's Chat!" ) @@ -456,10 +457,10 @@ def chat(chat_service_url, baseline, debug, stream): help=( """ \b - Start the Resin service. - This command will launch a uvicorn server that will serve the Resin API. + Start the Canopy service. + This command will launch a uvicorn server that will serve the Canopy API. - If you like to try out the chatbot, run `resin chat` in a separate terminal + If you like to try out the chatbot, run `canopy chat` in a separate terminal window. """ ) @@ -471,13 +472,14 @@ def chat(chat_service_url, baseline, debug, stream): @click.option("--reload/--no-reload", default=False, help="Set the server to reload on code changes. Defaults to False") @click.option("--config", "-c", default=None, - help="Path to a resin config file. Optional, otherwise configuration " + help="Path to a canopy config file. Optional, otherwise configuration " "defaults will be used.") def start(host: str, port: str, reload: bool, config: Optional[str]): note_msg = ( "🚨 Note 🚨\n" - "For debugging only. To run the Resin service in production, run the command:\n" - "gunicorn resin_cli.app:app --worker-class uvicorn.workers.UvicornWorker " + "For debugging only. To run the Canopy service in production, run the command:" + "\n" + "gunicorn canopy_cli.app:app --worker-class uvicorn.workers.UvicornWorker " f"--bind {host}:{port} --workers " ) for c in note_msg: @@ -485,7 +487,7 @@ def start(host: str, port: str, reload: bool, config: Optional[str]): time.sleep(0.01) click.echo() - click.echo(f"Starting Resin service on {host}:{port}") + click.echo(f"Starting Canopy service on {host}:{port}") start_service(host, port=port, reload=reload, config_file=config) @@ -493,26 +495,26 @@ def start(host: str, port: str, reload: bool, config: Optional[str]): help=( """ \b - Stop the Resin service. - This command will send a shutdown request to the Resin service. + Stop the Canopy service. + This command will send a shutdown request to the Canopy service. """ ) ) @click.option("url", "--url", default="http://0.0.0.0:8000", - help="URL of the Resin service to use. Defaults to http://0.0.0.0:8000") + help="URL of the Canopy service to use. Defaults to http://0.0.0.0:8000") def stop(url): # Check if the service was started using Gunicorn - res = subprocess.run(["pgrep", "-f", "gunicorn resin_cli.app:app"], + res = subprocess.run(["pgrep", "-f", "gunicorn canopy_cli.app:app"], capture_output=True) output = res.stdout.decode("utf-8").split() # If Gunicorn was used, kill all Gunicorn processes if output: - msg = ("It seems that Resin service was launched using Gunicorn.\n" + msg = ("It seems that Canopy service was launched using Gunicorn.\n" "Do you want to kill all Gunicorn processes?") click.confirm(click.style(msg, fg="red"), abort=True) try: - subprocess.run(["pkill", "-f", "gunicorn resin_cli.app:app"], check=True) + subprocess.run(["pkill", "-f", "gunicorn canopy_cli.app:app"], check=True) except subprocess.CalledProcessError: try: [os.kill(int(pid), signal.SIGINT) for pid in output] @@ -529,7 +531,7 @@ def stop(url): return res.ok except requests.exceptions.ConnectionError: msg = f""" - Could not find Resin service on {url}. + Could not find Canopy service on {url}. """ raise CLIError(msg) diff --git a/src/resin_cli/cli_spinner.py b/src/canopy_cli/cli_spinner.py similarity index 100% rename from src/resin_cli/cli_spinner.py rename to src/canopy_cli/cli_spinner.py diff --git a/src/resin_cli/data_loader/__init__.py b/src/canopy_cli/data_loader/__init__.py similarity index 100% rename from src/resin_cli/data_loader/__init__.py rename to src/canopy_cli/data_loader/__init__.py diff --git a/src/resin_cli/data_loader/data_loader.py b/src/canopy_cli/data_loader/data_loader.py similarity index 98% rename from src/resin_cli/data_loader/data_loader.py rename to src/canopy_cli/data_loader/data_loader.py index ee2d921a..ac0344ae 100644 --- a/src/resin_cli/data_loader/data_loader.py +++ b/src/canopy_cli/data_loader/data_loader.py @@ -10,7 +10,7 @@ from pydantic import ValidationError -from resin.models.data_models import Document +from canopy.models.data_models import Document class IDsNotUniqueError(ValueError): diff --git a/src/resin_cli/errors.py b/src/canopy_cli/errors.py similarity index 78% rename from src/resin_cli/errors.py rename to src/canopy_cli/errors.py index 1f54ed7e..e345dd39 100644 --- a/src/resin_cli/errors.py +++ b/src/canopy_cli/errors.py @@ -1,7 +1,7 @@ import click from click import ClickException -from resin_cli.data_loader.data_loader import format_multiline +from canopy_cli.data_loader.data_loader import format_multiline class CLIError(ClickException): diff --git a/tests/__init__.py b/tests/__init__.py index e0061e74..3a0ce978 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,4 +1,4 @@ from .unit.stubs.stub_tokenizer import StubTokenizer -from resin.tokenizer import Tokenizer +from canopy.tokenizer import Tokenizer Tokenizer.initialize(StubTokenizer) diff --git a/tests/e2e/test_app.py b/tests/e2e/test_app.py index 19a16b06..6bcf191c 100644 --- a/tests/e2e/test_app.py +++ b/tests/e2e/test_app.py @@ -8,10 +8,11 @@ from fastapi.testclient import TestClient from tenacity import retry, stop_after_attempt, wait_fixed -from resin.knowledge_base import KnowledgeBase +from canopy.knowledge_base import KnowledgeBase -from resin_cli.app import app -from resin_cli.api_models import HealthStatus, ContextUpsertRequest, ContextQueryRequest +from canopy_cli.app import app +from canopy_cli.api_models import (HealthStatus, ContextUpsertRequest, + ContextQueryRequest) from .. import Tokenizer upsert_payload = ContextUpsertRequest( @@ -50,7 +51,7 @@ def index_name(testrun_uid): def knowledge_base(index_name): pinecone.init() kb = KnowledgeBase(index_name=index_name) - kb.create_resin_index() + kb.create_canopy_index() return kb diff --git a/tests/system/knowledge_base/test_knowledge_base.py b/tests/system/knowledge_base/test_knowledge_base.py index 88d57ec5..8095239e 100644 --- a/tests/system/knowledge_base/test_knowledge_base.py +++ b/tests/system/knowledge_base/test_knowledge_base.py @@ -12,13 +12,13 @@ ) from dotenv import load_dotenv from datetime import datetime -from resin.knowledge_base import KnowledgeBase -from resin.knowledge_base.chunker import Chunker -from resin.knowledge_base.knowledge_base import INDEX_NAME_PREFIX -from resin.knowledge_base.models import DocumentWithScore -from resin.knowledge_base.record_encoder import RecordEncoder -from resin.knowledge_base.reranker import Reranker -from resin.models.data_models import Document, Query +from canopy.knowledge_base import KnowledgeBase +from canopy.knowledge_base.chunker import Chunker +from canopy.knowledge_base.knowledge_base import INDEX_NAME_PREFIX +from canopy.knowledge_base.models import DocumentWithScore +from canopy.knowledge_base.record_encoder import RecordEncoder +from canopy.knowledge_base.reranker import Reranker +from canopy.models.data_models import Document, Query from tests.unit.stubs.stub_record_encoder import StubRecordEncoder from tests.unit.stubs.stub_dense_encoder import StubDenseEncoder from tests.unit.stubs.stub_chunker import StubChunker @@ -71,7 +71,7 @@ def knowledge_base(index_full_name, index_name, chunker, encoder): kb = KnowledgeBase(index_name=index_name, record_encoder=encoder, chunker=chunker) - kb.create_resin_index() + kb.create_canopy_index() return kb @@ -344,7 +344,7 @@ def test_create_existing_index_no_connect(index_full_name, index_name): record_encoder=StubRecordEncoder(StubDenseEncoder(dimension=3)), chunker=StubChunker(num_chunks_per_doc=2)) with pytest.raises(RuntimeError) as e: - kb.create_resin_index() + kb.create_canopy_index() assert f"Index {index_full_name} already exists" in str(e.value) @@ -447,7 +447,7 @@ def test_create_with_text_in_indexed_field_raise(index_name, kb = KnowledgeBase(index_name=index_name, record_encoder=encoder, chunker=chunker) - kb.create_resin_index(indexed_fields=["id", "text", "metadata"]) + kb.create_canopy_index(indexed_fields=["id", "text", "metadata"]) assert "The 'text' field cannot be used for metadata filtering" in str(e.value) @@ -459,7 +459,7 @@ def test_create_with_index_encoder_dimension_none(index_name, chunker): kb = KnowledgeBase(index_name=index_name, record_encoder=encoder, chunker=chunker) - kb.create_resin_index() + kb.create_canopy_index() assert "Could not infer dimension from encoder" in str(e.value) @@ -481,7 +481,7 @@ def test_create_bad_credentials(set_bad_credentials, index_name, chunker, encode record_encoder=encoder, chunker=chunker) with pytest.raises(RuntimeError) as e: - kb.create_resin_index() + kb.create_canopy_index() assert "Please check your credentials" in str(e.value) diff --git a/tests/system/llm/test_openai.py b/tests/system/llm/test_openai.py index ef5ad677..879eeca5 100644 --- a/tests/system/llm/test_openai.py +++ b/tests/system/llm/test_openai.py @@ -2,10 +2,10 @@ import pytest -from resin.models.data_models import Role, MessageBase # noqa -from resin.models.api_models import ChatResponse, StreamingChatChunk # noqa -from resin.llm.openai import OpenAILLM # noqa -from resin.llm.models import \ +from canopy.models.data_models import Role, MessageBase # noqa +from canopy.models.api_models import ChatResponse, StreamingChatChunk # noqa +from canopy.llm.openai import OpenAILLM # noqa +from canopy.llm.models import \ Function, FunctionParameters, FunctionArrayProperty, ModelParams # noqa from openai import InvalidRequestError # noqa diff --git a/tests/system/query_generator/test_query_generator_integration.py b/tests/system/query_generator/test_query_generator_integration.py index 51a4d275..1bd8ffda 100644 --- a/tests/system/query_generator/test_query_generator_integration.py +++ b/tests/system/query_generator/test_query_generator_integration.py @@ -2,10 +2,10 @@ import pytest -from resin.llm.openai import OpenAILLM # noqa -from resin.models.data_models import MessageBase, Query # noqa -from resin.chat_engine.query_generator import FunctionCallingQueryGenerator # noqa -from resin.chat_engine.prompt_builder import PromptBuilder # noqa +from canopy.llm.openai import OpenAILLM # noqa +from canopy.models.data_models import MessageBase, Query # noqa +from canopy.chat_engine.query_generator import FunctionCallingQueryGenerator # noqa +from canopy.chat_engine.prompt_builder import PromptBuilder # noqa from typing import List # noqa diff --git a/tests/system/utils/test_config.py b/tests/system/utils/test_config.py index 84dbf1fe..0701f358 100644 --- a/tests/system/utils/test_config.py +++ b/tests/system/utils/test_config.py @@ -3,9 +3,9 @@ import pytest import yaml -from resin.chat_engine import ChatEngine -from resin.context_engine import ContextEngine -from resin.knowledge_base import KnowledgeBase +from canopy.chat_engine import ChatEngine +from canopy.context_engine import ContextEngine +from canopy.knowledge_base import KnowledgeBase DEFAULT_COFIG_PATH = 'config/config.yaml' @@ -35,7 +35,7 @@ def test_default_config_matches_code_defaults(temp_index_name): def assert_identical_components(loaded_component, default_component): assert type(loaded_component) == type(default_component) # noqa: E721 - if not loaded_component.__module__.startswith("resin"): + if not loaded_component.__module__.startswith("canopy"): return for key, value in default_component.__dict__.items(): diff --git a/tests/unit/chat_engine/test_chat_engine.py b/tests/unit/chat_engine/test_chat_engine.py index 1a0e6dd5..f77e552a 100644 --- a/tests/unit/chat_engine/test_chat_engine.py +++ b/tests/unit/chat_engine/test_chat_engine.py @@ -3,14 +3,14 @@ import pytest import random -from resin.chat_engine import ChatEngine -from resin.chat_engine.query_generator import QueryGenerator -from resin.context_engine import ContextEngine -from resin.context_engine.models import ContextQueryResult, ContextSnippet -from resin.llm import BaseLLM -from resin.llm.models import SystemMessage -from resin.models.api_models import ChatResponse, _Choice, TokenCounts -from resin.models.data_models import MessageBase, Query, Context, Role +from canopy.chat_engine import ChatEngine +from canopy.chat_engine.query_generator import QueryGenerator +from canopy.context_engine import ContextEngine +from canopy.context_engine.models import ContextQueryResult, ContextSnippet +from canopy.llm import BaseLLM +from canopy.llm.models import SystemMessage +from canopy.models.api_models import ChatResponse, _Choice, TokenCounts +from canopy.models.data_models import MessageBase, Query, Context, Role from .. import random_words MOCK_SYSTEM_PROMPT = "This is my mock prompt" diff --git a/tests/unit/chunker/base_test_chunker.py b/tests/unit/chunker/base_test_chunker.py index 64102f9b..0052e204 100644 --- a/tests/unit/chunker/base_test_chunker.py +++ b/tests/unit/chunker/base_test_chunker.py @@ -1,6 +1,6 @@ import pytest from abc import ABC, abstractmethod -from resin.models.data_models import Document +from canopy.models.data_models import Document class BaseTestChunker(ABC): diff --git a/tests/unit/chunker/test_markdown_chunker.py b/tests/unit/chunker/test_markdown_chunker.py index ada9b2a3..db9692b9 100644 --- a/tests/unit/chunker/test_markdown_chunker.py +++ b/tests/unit/chunker/test_markdown_chunker.py @@ -1,8 +1,8 @@ import pytest -from resin.knowledge_base.chunker import MarkdownChunker -from resin.knowledge_base.models import KBDocChunk -from resin.models.data_models import Document +from canopy.knowledge_base.chunker import MarkdownChunker +from canopy.knowledge_base.models import KBDocChunk +from canopy.models.data_models import Document from tests.unit.chunker.base_test_chunker import BaseTestChunker diff --git a/tests/unit/chunker/test_recursive_character_chunker.py b/tests/unit/chunker/test_recursive_character_chunker.py index 3a3cc8fe..e3fdbd22 100644 --- a/tests/unit/chunker/test_recursive_character_chunker.py +++ b/tests/unit/chunker/test_recursive_character_chunker.py @@ -1,7 +1,7 @@ import pytest -from resin.knowledge_base.chunker.recursive_character \ +from canopy.knowledge_base.chunker.recursive_character \ import RecursiveCharacterChunker -from resin.knowledge_base.models import KBDocChunk +from canopy.knowledge_base.models import KBDocChunk from tests.unit.chunker.base_test_chunker import BaseTestChunker diff --git a/tests/unit/chunker/test_stub_chunker.py b/tests/unit/chunker/test_stub_chunker.py index 78eb91a3..6855d417 100644 --- a/tests/unit/chunker/test_stub_chunker.py +++ b/tests/unit/chunker/test_stub_chunker.py @@ -1,6 +1,6 @@ import pytest -from resin.knowledge_base.models import KBDocChunk +from canopy.knowledge_base.models import KBDocChunk from .base_test_chunker import BaseTestChunker from ..stubs.stub_chunker import StubChunker diff --git a/tests/unit/chunker/test_token_chunker.py b/tests/unit/chunker/test_token_chunker.py index 463dc99f..b5550e3c 100644 --- a/tests/unit/chunker/test_token_chunker.py +++ b/tests/unit/chunker/test_token_chunker.py @@ -1,9 +1,9 @@ import pytest -from resin.knowledge_base.models import KBDocChunk -from resin.models.data_models import Document +from canopy.knowledge_base.models import KBDocChunk +from canopy.models.data_models import Document from .base_test_chunker import BaseTestChunker -from resin.knowledge_base.chunker.token_chunker import TokenChunker +from canopy.knowledge_base.chunker.token_chunker import TokenChunker class TestTokenChunker(BaseTestChunker): diff --git a/tests/unit/cli/test_data_loader.py b/tests/unit/cli/test_data_loader.py index ff11c651..bc71add1 100644 --- a/tests/unit/cli/test_data_loader.py +++ b/tests/unit/cli/test_data_loader.py @@ -3,8 +3,8 @@ import json import pandas as pd -from resin.models.data_models import Document -from resin_cli.data_loader.data_loader import ( +from canopy.models.data_models import Document +from canopy_cli.data_loader.data_loader import ( IDsNotUniqueError, DocumentsValidationError, load_from_path, diff --git a/tests/unit/context_builder/test_stuffing_context_builder.py b/tests/unit/context_builder/test_stuffing_context_builder.py index f8ec3220..bfd9a899 100644 --- a/tests/unit/context_builder/test_stuffing_context_builder.py +++ b/tests/unit/context_builder/test_stuffing_context_builder.py @@ -1,10 +1,10 @@ -from resin.context_engine.models import \ +from canopy.context_engine.models import \ ContextSnippet, ContextQueryResult -from resin.models.data_models import Context +from canopy.models.data_models import Context from ..stubs.stub_tokenizer import StubTokenizer -from resin.knowledge_base.models import \ +from canopy.knowledge_base.models import \ QueryResult, DocumentWithScore -from resin.context_engine.context_builder import StuffingContextBuilder +from canopy.context_engine.context_builder import StuffingContextBuilder class TestStuffingContextBuilder: diff --git a/tests/unit/context_engine/test_context_engine.py b/tests/unit/context_engine/test_context_engine.py index 41e87079..66e7ac7e 100644 --- a/tests/unit/context_engine/test_context_engine.py +++ b/tests/unit/context_engine/test_context_engine.py @@ -1,11 +1,11 @@ import pytest from unittest.mock import create_autospec -from resin.context_engine import ContextEngine -from resin.context_engine.context_builder.base import ContextBuilder -from resin.knowledge_base.base import BaseKnowledgeBase -from resin.knowledge_base.models import QueryResult, DocumentWithScore -from resin.models.data_models import Query, Context, ContextContent +from canopy.context_engine import ContextEngine +from canopy.context_engine.context_builder.base import ContextBuilder +from canopy.knowledge_base.base import BaseKnowledgeBase +from canopy.knowledge_base.models import QueryResult, DocumentWithScore +from canopy.models.data_models import Query, Context, ContextContent class TestContextEngine: diff --git a/tests/unit/history_builder/test_recent_history_builder.py b/tests/unit/history_builder/test_recent_history_builder.py index feecb77c..b1dd1db6 100644 --- a/tests/unit/history_builder/test_recent_history_builder.py +++ b/tests/unit/history_builder/test_recent_history_builder.py @@ -1,7 +1,7 @@ import pytest -from resin.chat_engine.history_pruner import RecentHistoryPruner -from resin.llm.models import UserMessage, AssistantMessage +from canopy.chat_engine.history_pruner import RecentHistoryPruner +from canopy.llm.models import UserMessage, AssistantMessage @pytest.fixture diff --git a/tests/unit/prompt_builder/test_prompt_builder.py b/tests/unit/prompt_builder/test_prompt_builder.py index 8f71b455..865d8de4 100644 --- a/tests/unit/prompt_builder/test_prompt_builder.py +++ b/tests/unit/prompt_builder/test_prompt_builder.py @@ -2,11 +2,11 @@ import pytest -from resin.chat_engine.exceptions import InvalidRequestError -from resin.chat_engine.history_pruner.base import HistoryPruner -from resin.chat_engine.models import HistoryPruningMethod -from resin.chat_engine.prompt_builder import PromptBuilder -from resin.models.data_models import MessageBase, Role +from canopy.chat_engine.exceptions import InvalidRequestError +from canopy.chat_engine.history_pruner.base import HistoryPruner +from canopy.chat_engine.models import HistoryPruningMethod +from canopy.chat_engine.prompt_builder import PromptBuilder +from canopy.models.data_models import MessageBase, Role @pytest.fixture diff --git a/tests/unit/query_generators/test_function_calling_query_generator.py b/tests/unit/query_generators/test_function_calling_query_generator.py index 2d47a71f..be405593 100644 --- a/tests/unit/query_generators/test_function_calling_query_generator.py +++ b/tests/unit/query_generators/test_function_calling_query_generator.py @@ -3,15 +3,15 @@ import pytest -from resin.chat_engine.prompt_builder import PromptBuilder -from resin.chat_engine.query_generator.function_calling \ +from canopy.chat_engine.prompt_builder import PromptBuilder +from canopy.chat_engine.query_generator.function_calling \ import (FunctionCallingQueryGenerator, DEFAULT_FUNCTION_DESCRIPTION, DEFAULT_SYSTEM_PROMPT, ) -from resin.llm import BaseLLM -from resin.llm.models import (ModelParams, Function, - FunctionParameters, FunctionArrayProperty, - UserMessage, ) -from resin.models.data_models import Query +from canopy.llm import BaseLLM +from canopy.llm.models import (ModelParams, Function, + FunctionParameters, FunctionArrayProperty, + UserMessage, ) +from canopy.models.data_models import Query class TestFunctionCallingQueryGenerator: diff --git a/tests/unit/record_encoder/base_test_record_encoder.py b/tests/unit/record_encoder/base_test_record_encoder.py index 0c1c2008..627d12ca 100644 --- a/tests/unit/record_encoder/base_test_record_encoder.py +++ b/tests/unit/record_encoder/base_test_record_encoder.py @@ -2,8 +2,8 @@ import math from abc import ABC, abstractmethod -from resin.knowledge_base.models import KBDocChunk, KBEncodedDocChunk, KBQuery -from resin.models.data_models import Query +from canopy.knowledge_base.models import KBDocChunk, KBEncodedDocChunk, KBQuery +from canopy.models.data_models import Query class BaseTestRecordEncoder(ABC): diff --git a/tests/unit/record_encoder/test_dense_record_encoder.py b/tests/unit/record_encoder/test_dense_record_encoder.py index c2b7cd8a..5cf174ad 100644 --- a/tests/unit/record_encoder/test_dense_record_encoder.py +++ b/tests/unit/record_encoder/test_dense_record_encoder.py @@ -1,6 +1,6 @@ import pytest -from resin.knowledge_base.record_encoder import DenseRecordEncoder +from canopy.knowledge_base.record_encoder import DenseRecordEncoder from .base_test_record_encoder import BaseTestRecordEncoder from ..stubs.stub_dense_encoder import StubDenseEncoder diff --git a/tests/unit/record_encoder/test_openai_record_encoder.py b/tests/unit/record_encoder/test_openai_record_encoder.py index fd5333ec..b53432fb 100644 --- a/tests/unit/record_encoder/test_openai_record_encoder.py +++ b/tests/unit/record_encoder/test_openai_record_encoder.py @@ -1,7 +1,7 @@ import pytest from pinecone_text.dense.openai_encoder import OpenAIEncoder -from resin.knowledge_base.record_encoder.openai import OpenAIRecordEncoder +from canopy.knowledge_base.record_encoder.openai import OpenAIRecordEncoder from .base_test_record_encoder import BaseTestRecordEncoder from unittest.mock import Mock diff --git a/tests/unit/stubs/stub_chunker.py b/tests/unit/stubs/stub_chunker.py index aceb214f..7f6058ad 100644 --- a/tests/unit/stubs/stub_chunker.py +++ b/tests/unit/stubs/stub_chunker.py @@ -1,7 +1,7 @@ from typing import List -from resin.knowledge_base.chunker.base import Chunker -from resin.knowledge_base.models import KBDocChunk -from resin.models.data_models import Document +from canopy.knowledge_base.chunker.base import Chunker +from canopy.knowledge_base.models import KBDocChunk +from canopy.models.data_models import Document class StubChunker(Chunker): diff --git a/tests/unit/stubs/stub_record_encoder.py b/tests/unit/stubs/stub_record_encoder.py index 9af5d387..2b77f170 100644 --- a/tests/unit/stubs/stub_record_encoder.py +++ b/tests/unit/stubs/stub_record_encoder.py @@ -1,8 +1,8 @@ from typing import List -from resin.knowledge_base.record_encoder import RecordEncoder -from resin.knowledge_base.models import KBQuery, KBDocChunk, KBEncodedDocChunk -from resin.models.data_models import Query +from canopy.knowledge_base.record_encoder import RecordEncoder +from canopy.knowledge_base.models import KBQuery, KBDocChunk, KBEncodedDocChunk +from canopy.models.data_models import Query from .stub_dense_encoder import StubDenseEncoder diff --git a/tests/unit/stubs/stub_tokenizer.py b/tests/unit/stubs/stub_tokenizer.py index 6c175230..82c4f6f9 100644 --- a/tests/unit/stubs/stub_tokenizer.py +++ b/tests/unit/stubs/stub_tokenizer.py @@ -1,6 +1,6 @@ from typing import List -from resin.tokenizer.base import BaseTokenizer -from resin.models.data_models import Messages +from canopy.tokenizer.base import BaseTokenizer +from canopy.models.data_models import Messages class StubTokenizer(BaseTokenizer): diff --git a/tests/unit/tokenizer/test_openai_tokenizer.py b/tests/unit/tokenizer/test_openai_tokenizer.py index 71937be9..d1942727 100644 --- a/tests/unit/tokenizer/test_openai_tokenizer.py +++ b/tests/unit/tokenizer/test_openai_tokenizer.py @@ -1,6 +1,6 @@ import pytest -from resin.tokenizer import OpenAITokenizer -from resin.models.data_models import MessageBase, Role +from canopy.tokenizer import OpenAITokenizer +from canopy.models.data_models import MessageBase, Role from .base_test_tokenizer import BaseTestTokenizer diff --git a/tests/unit/tokenizer/test_stub_tokenizer.py b/tests/unit/tokenizer/test_stub_tokenizer.py index 25ecd9e6..71b7b3ec 100644 --- a/tests/unit/tokenizer/test_stub_tokenizer.py +++ b/tests/unit/tokenizer/test_stub_tokenizer.py @@ -1,6 +1,6 @@ import pytest -from resin.models.data_models import MessageBase, Role +from canopy.models.data_models import MessageBase, Role from .base_test_tokenizer import BaseTestTokenizer from ..stubs.stub_tokenizer import StubTokenizer diff --git a/tests/unit/tokenizer/test_tokenizer_singleton.py b/tests/unit/tokenizer/test_tokenizer_singleton.py index bb7669fe..26e3001e 100644 --- a/tests/unit/tokenizer/test_tokenizer_singleton.py +++ b/tests/unit/tokenizer/test_tokenizer_singleton.py @@ -1,5 +1,5 @@ import pytest -from resin.tokenizer import Tokenizer +from canopy.tokenizer import Tokenizer from ..stubs.stub_tokenizer import StubTokenizer diff --git a/tests/unit/utils/_stub_classes.py b/tests/unit/utils/_stub_classes.py index a9b6954d..fa5a09e0 100644 --- a/tests/unit/utils/_stub_classes.py +++ b/tests/unit/utils/_stub_classes.py @@ -1,7 +1,7 @@ import abc from typing import Optional -from resin.utils.config import ConfigurableMixin +from canopy.utils.config import ConfigurableMixin # A base class that inherits from ConfigurableMixin, with multiple derived classes