From 4f67c33371d20a183648da227b24a4a47fab1af7 Mon Sep 17 00:00:00 2001 From: eff-kay Date: Sun, 3 Nov 2024 05:48:18 -0500 Subject: [PATCH] pypi release --- LICENSE | 222 ++++++++++++++++-- README.md | 190 ++++++--------- example_configs/bert-uncased.yaml | 11 + magemaker/__init__.py | 36 +++ {src => magemaker}/config.py | 17 +- {src => magemaker}/console.py | 0 {src => magemaker}/huggingface/__init__.py | 0 {src => magemaker}/huggingface/hf_hub_api.py | 8 +- {src => magemaker}/main.py | 43 ++-- magemaker/runner.py | 175 ++++++++++++++ {src => magemaker}/sagemaker/__init__.py | 0 {src => magemaker}/sagemaker/create_model.py | 20 +- {src => magemaker}/sagemaker/delete_model.py | 2 +- .../sagemaker/fine_tune_model.py | 12 +- .../sagemaker/query_endpoint.py | 20 +- {src => magemaker}/sagemaker/resources.py | 8 +- .../sagemaker/search_jumpstart_models.py | 4 +- magemaker/schemas/__init__.py | 4 + {src => magemaker}/schemas/deployment.py | 2 +- {src => magemaker}/schemas/model.py | 6 +- {src => magemaker}/schemas/query.py | 0 {src => magemaker}/schemas/training.py | 4 +- magemaker/scripts/preflight.sh | 38 +++ {scripts => magemaker/scripts}/setup_role.sh | 0 {src => magemaker}/session.py | 0 {src => magemaker/utils}/__init__.py | 0 {src => magemaker}/utils/aws_utils.py | 0 {src => magemaker}/utils/format.py | 0 {src => magemaker}/utils/model_utils.py | 12 +- {src => magemaker}/utils/rich_utils.py | 0 {src => magemaker}/yaml.py | 0 model_manager.py | 94 -------- pyproject.toml | 18 +- server.py | 10 +- src/schemas/__init__.py | 4 - src/utils/__init__.py | 0 36 files changed, 643 insertions(+), 317 deletions(-) create mode 100644 example_configs/bert-uncased.yaml create mode 100644 magemaker/__init__.py rename {src => magemaker}/config.py (82%) rename {src => magemaker}/console.py (100%) rename {src => magemaker}/huggingface/__init__.py (100%) rename {src => magemaker}/huggingface/hf_hub_api.py (79%) rename {src => magemaker}/main.py (86%) create mode 100644 magemaker/runner.py rename {src => magemaker}/sagemaker/__init__.py (100%) rename {src => magemaker}/sagemaker/create_model.py (93%) rename {src => magemaker}/sagemaker/delete_model.py (89%) rename {src => magemaker}/sagemaker/fine_tune_model.py (93%) rename {src => magemaker}/sagemaker/query_endpoint.py (93%) rename {src => magemaker}/sagemaker/resources.py (94%) rename {src => magemaker}/sagemaker/search_jumpstart_models.py (89%) create mode 100644 magemaker/schemas/__init__.py rename {src => magemaker}/schemas/deployment.py (96%) rename {src => magemaker}/schemas/model.py (88%) rename {src => magemaker}/schemas/query.py (100%) rename {src => magemaker}/schemas/training.py (93%) create mode 100755 magemaker/scripts/preflight.sh rename {scripts => magemaker/scripts}/setup_role.sh (100%) mode change 100644 => 100755 rename {src => magemaker}/session.py (100%) rename {src => magemaker/utils}/__init__.py (100%) rename {src => magemaker}/utils/aws_utils.py (100%) rename {src => magemaker}/utils/format.py (100%) rename {src => magemaker}/utils/model_utils.py (92%) rename {src => magemaker}/utils/rich_utils.py (100%) rename {src => magemaker}/yaml.py (100%) delete mode 100644 model_manager.py delete mode 100644 src/schemas/__init__.py delete mode 100644 src/utils/__init__.py diff --git a/LICENSE b/LICENSE index 8d80b47..8ef4638 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,201 @@ -MIT License - -Copyright (c) 2024 OpenFoundry - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +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 [2024] [SlashML Corp.] + +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. \ No newline at end of file diff --git a/README.md b/README.md index bb264a8..385b7d7 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,7 @@
-

Model Manager v0.1, by

- -![openfoundry white](https://github.com/openfoundry-ai/model_manager/assets/152243036/01b64d39-1402-45b6-8dce-8b4626c41935) +

Magemaker v0.1, by SlashML

Deploy open source AI models to AWS in minutes. @@ -21,7 +19,7 @@

Table of Contents
  1. - About Model Manager + About Magemaker
  2. Getting Started @@ -30,7 +28,7 @@
  3. Installation
  4. -
  5. Using Model Manager
  6. +
  7. Using Magemaker
  8. What we're working on next
  9. Known issues
  10. Contributing
  11. @@ -40,30 +38,18 @@ -## About Model Manager -Model Manager is a Python tool that simplifies the process of deploying an open source AI model to your own cloud. Instead of spending hours digging through documentation to figure out how to get AWS working, Model Manager lets you deploy open source AI models directly from the command line. - -Choose a model from Hugging Face or SageMaker, and Model Manager will spin up a SageMaker instance with a ready-to-query endpoint in minutes. - -Here we’re deploying Microsoft’s Phi2. Larger models such as this take about 10 minutes to spin up. - -https://github.com/openfoundry-ai/model_manager/assets/164248540/f7fbf9ce-04c3-49b0-b5be-2977b5cc90af - -
    -Once the model is running, you can query it to get a response. - -![Screenshot 2024-03-20 at 6 01 44 PM](https://github.com/openfoundry-ai/model_manager/assets/164248540/20b46f8f-da01-4cc7-8343-e647b27ba7c6) - - -

    (back to top)

    +## About Magemaker +Magemaker is a Python tool that simplifies the process of deploying an open source AI model to your own cloud. Instead of spending hours digging through documentation to figure out how to get AWS working, Magemaker lets you deploy open source AI models directly from the command line. +Choose a model from Hugging Face or SageMaker, and Magemaker will spin up a SageMaker instance with a ready-to-query endpoint in minutes.
    ## Getting Started -Model Manager works with AWS. Azure and GCP support are coming soon! +Magemaker works with AWS. Azure and GCP support are coming soon! + To get a local copy up and running follow these simple steps. ### Prerequisites @@ -73,38 +59,39 @@ To get a local copy up and running follow these simple steps. * Quota for AWS SageMaker instances (by default, you get 2 instances of ml.m5.xlarge for free) * Certain Hugging Face models (e.g. Llama2) require an access token ([hf docs](https://huggingface.co/docs/hub/en/models-gated#access-gated-models-as-a-user)) - -### Installation +### Configuration **Step 1: Set up AWS and SageMaker** To get started, you’ll need an AWS account which you can create at https://aws.amazon.com/. Then you’ll need to create access keys for SageMaker. -We made a walkthrough video to show you how to get set up with your SageMaker access keys in 2 minutes. +We wrote up the steps in [Google Doc](https://docs.google.com/document/d/1NvA6uZmppsYzaOdkcgNTRl7Nb4LbpP9Koc4H_t5xNSg/edit?tab=t.0#heading=h.farbxuv3zrzm) as well. -https://github.com/openfoundry-ai/model_manager/assets/164248540/52b0dcee-87cd-48de-9251-b2d3571abf61 -If you prefer a written doc, we wrote up the steps in [Google Doc](https://docs.google.com/document/d/1kLzPU43kvLAoYzmBfvAkINmXZ24JzAp_fdBIYjJRXvU/edit?usp=sharing) as well. +### Installing the package -**Step 2: Set up Model Manager** - -You should now have your Access Key and Secret from SageMaker. Now you can set up Model Manager! Clone the repo to your local machine, and then run the setup script in the repo: +**Step 1** ```sh - bash setup.sh +pip install magemaker ``` -This will configure the AWS client so you’re ready to start deploying models. You’ll be prompted to enter your Access Key and Secret here. You can also specify your AWS region. The default is us-east-1. You only need to change this if your SageMaker instance quota is in a different region. +**Step 2: Running magemaker** -Optional: If you have a Hugging Face Hub Token, you can add it to `.env` that was generated by the setup script and add it with the key: +Run it by simply doing the following: ```sh -HUGGING_FACE_HUB_KEY="KeyValueHere" +magemaker ``` -This will allow you to use models with access restrictions such as Llama2 as long as your Hugging Face account has permission to do so. +If this is your first time running this command. It will configure the AWS client so you’re ready to start deploying models. You’ll be prompted to enter your Access Key and Secret here. You can also specify your AWS region. The default is us-east-1. You only need to change this if your SageMaker instance quota is in a different region. + +Once configured, it will create a `.env` file and save the credentials there. You can also add your Hugging Face Hub Token to this file if you have one. +```sh +HUGGING_FACE_HUB_KEY="KeyValueHere" +```

    (back to top)

    @@ -113,29 +100,63 @@ This will allow you to use models with access restrictions such as Llama2 as lon
    -## Using Model Manager -After you’ve set up AWS and Model Manager per the above, run Model Manager using python or python3: -```sh -python3 model_manager.py -``` - -![home screen](https://github.com/openfoundry-ai/model_manager/assets/164248540/22ede5aa-99e3-4191-bca8-3021c6b572e7) +## Using Magemaker +### Deploying models from dropdown -Now you’re ready to start shipping models onto your cloud! -
    -
    +When you run `magemaker` comamnd it will give you an interactive menu to deploy models. You can choose from a dropdown of models to deploy. -### Deploying models +#### Deploying Hugging Face models +If you're deploying with Hugging Face, copy/paste the full model name from Hugging Face. For example, `google-bert/bert-base-uncased`. Note that you’ll need larger, more expensive instance types in order to run bigger models. It takes anywhere from 2 minutes (for smaller models) to 10+ minutes (for large models) to spin up the instance with your model. -There are three ways from where you can deploy models: Hugging Face, SageMaker, or your own custom model. Use whichever works for you! If you're deploying with Hugging Face, copy/paste the full model name from Hugging Face. For example, `google-bert/bert-base-uncased`. Note that you’ll need larger, more expensive instance types in order to run bigger models. It takes anywhere from 2 minutes (for smaller models) to 10+ minutes (for large models) to spin up the instance with your model. If you are deploying a Sagemaker model, select a framework and search from a model. If you a deploying a custom model, provide either a valid S3 path or a local path (and the tool will automatically upload it for you). Once deployed, we will generate a YAML file with the deployment and model under `/configs` +#### Deploying Sagemaker models +If you are deploying a Sagemaker model, select a framework and search from a model. If you a deploying a custom model, provide either a valid S3 path or a local path (and the tool will automatically upload it for you). Once deployed, we will generate a YAML file with the deployment and model in the `CONFIG_DIR=.magemaker_config` folder. You can modify the path to this folder by setting the `CONFIG_DIR` environment variable. #### Deploy using a yaml file -For future deploys, we recommend deploying through a yaml file for reproducability and IAC. From the cli, you can deploy a model without going through all the menus. You can even integrate us with your Github Actions to deploy on PR merge. Deploy via YAML files simply by passing the `--deploy` option with local path like so: +We recommend deploying through a yaml file for reproducability and IAC. From the cli, you can deploy a model without going through all the menus. You can even integrate us with your Github Actions to deploy on PR merge. Deploy via YAML files simply by passing the `--deploy` option with local path like so: + +``` +magemaker --deploy .magemaker_config/bert-base-uncased.yaml ``` -python model_manager.py --deploy ./example_configs/llama7b.yaml + +Following is a sample yaml file for deploying a model the same google bert model mentioned above: + +```yaml +deployment: !Deployment + destination: aws + # Endpoint name matches model_id for querying atm. + endpoint_name: test-bert-uncased + instance_count: 1 + instance_type: ml.m5.xlarge + +models: +- !Model + id: google-bert/bert-base-uncased + source: huggingface +``` + +Following is a yaml file for deploying a llama model from HF: +```yaml +deployment: !Deployment + destination: aws + endpoint_name: test-llama2-7b + instance_count: 1 + instance_type: ml.g5.12xlarge + num_gpus: 4 + # quantization: bitsandbytes + +models: +- !Model + id: meta-llama/Meta-Llama-3-8B-Instruct + source: huggingface + predict: + temperature: 0.9 + top_p: 0.9 + top_k: 20 + max_new_tokens: 250 ``` +

    @@ -147,9 +168,7 @@ If you’re using the `ml.m5.xlarge` instance type, here are some small Hugging - **Type:** Fill Mask: tries to complete your sentence like Madlibs - **Query format:** text string with `[MASK]` somewhere in it that you wish for the transformer to fill - - ![fill mask bert query](https://github.com/openfoundry-ai/model_manager/assets/164248540/a8a6d8e9-183f-4c85-afe8-b9c21d8aa687) - +-

    @@ -157,50 +176,10 @@ If you’re using the `ml.m5.xlarge` instance type, here are some small Hugging - **Type:** Feature extraction: turns text into a 384d vector embedding for semantic search / clustering - **Query format:** "*type out a sentence like this one.*" - - ![sentence transformer query](https://github.com/openfoundry-ai/model_manager/assets/164248540/57b4da43-03bb-4642-892b-5f287dfce0d8) - -
    -
    - -**Model: [deepset/roberta-base-squad2](https://huggingface.co/deepset/roberta-base-squad2)** - -- **Type:** Question answering; provide a question and some context from which the transformer will answer the question. -- **Query format:** A dict with two keys: `question` and `context`. For our tool, we will prompt you a second time to provide the context. - - ![roberta eqa query](https://github.com/openfoundry-ai/model_manager/assets/164248540/2054fdb7-1f3d-4bfe-a806-c5ebde8ad20d)

    -### Querying models -There are three ways to query a model you’ve deployed: you can query it using the Model Manager script, spin up a FastAPI server, or call it directly from your code using SageMaker’s API. - -To spin up a FastAPI server, run -``` -uvicorn server:app --reload -``` -This will create a server running at `0.0.0.0` on port 8000 which you can query against from your app. There are 2 endpoints: -1. `GET /endpoint/{endpoint_name}`: Get information about a deployed endpoint -2. `POST /endpoint/{endpoint_name}/query`: Query a model for inference. The request expects a JSON body with only the `query` key being required. `context` is required for some types of models (such as question-answering). `parameters` can be passed for text-generation/LLM models to further control the output of the model. -``` -{ - "query": "string", - "context": "string", - "parameters": { - "max_length": 0, - "max_new_tokens": 0, - "repetition_penalty": 0, - "temperature": 0, - "top_k": 0, - "top_p": 0 - } -} -``` - -Querying within Model Manager currently works for text-based models. Image generation, multi-modal, etc. models are not yet supported. - -You can query all deployed models using the SageMaker API. Documentation for how to do this can be found [here](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_runtime_InvokeEndpoint.html). ### Deactivating models @@ -210,7 +189,6 @@ Any model endpoints you spin up will run continuously unless you deactivate them

    (back to top)

    -
    @@ -227,45 +205,25 @@ Any model endpoints you spin up will run continuously unless you deactivate them
    ## Known issues -- [ ] Querying within Model Manager currently only works with text-based model - doesn’t work with multimodal, image generation, etc. -- [ ] Model versions are static. +- [ ] Querying within Magemaker currently only works with text-based model - doesn’t work with multimodal, image generation, etc. - [ ] Deleting a model is not instant, it may show up briefly after it was queued for deletion - [ ] Deploying the same model within the same minute will break -See [open issues](https://github.com/openfoundry-ai/model_manager/issues) for a full list of known issues and proposed features. -

    (back to top)

    - -
    - -## Contributing - -If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". - -If you found this useful, please give us a star! Thanks again! - -

    (back to top)

    - - -
    ## License -Distributed under the MIT License. See `LICENSE.txt` for more information. - -

    (back to top)

    - - +Distributed under the Apache 2.0 License. See `LICENSE` for more information.
    ## Contact -You can reach us, Arthur & Tyler, at [hello@openfoundry.ai](mailto:hello@openfoundry.ai). +You can reach us, faizan & jneid, at [support@slashml.com](mailto:support@slashml.com). We’d love to hear from you! We’re excited to learn how we can make this more valuable for the community and welcome any and all feedback and suggestions. diff --git a/example_configs/bert-uncased.yaml b/example_configs/bert-uncased.yaml new file mode 100644 index 0000000..f0f144c --- /dev/null +++ b/example_configs/bert-uncased.yaml @@ -0,0 +1,11 @@ +deployment: !Deployment + destination: aws + # Endpoint name matches model_id for querying atm. + endpoint_name: test-bert-uncased + instance_count: 1 + instance_type: ml.m5.xlarge + +models: +- !Model + id: google-bert/bert-base-uncased + source: huggingface \ No newline at end of file diff --git a/magemaker/__init__.py b/magemaker/__init__.py new file mode 100644 index 0000000..66cff8c --- /dev/null +++ b/magemaker/__init__.py @@ -0,0 +1,36 @@ +import os + +import pkg_resources +import subprocess + +print('test') +def pre_flight(): + print('running preflight checks') + + + scripts_dir = pkg_resources.resource_filename('magemaker', 'scripts') + setup_script = os.path.join(scripts_dir, 'preflight.sh') + setup_role_script = os.path.join(scripts_dir, 'setup_role.sh') + + # Make scripts executable + os.chmod(setup_script, 0o755) + os.chmod(setup_role_script, 0o755) + + + # Use subprocess instead of os.system for better error handling + try: + subprocess.run(['bash', setup_script], check=True) + except subprocess.CalledProcessError as e: + print(f"Error executing setup.sh: {e}") + return 1 + except FileNotFoundError: + print("Could not find setup.sh in the installed package") + return 1 + + # Rest of your main function code + return 0 + +pre_flight() +# print('sometihng', os.getpwd()) +# if (not os.path.exists(os.path.expanduser('~/.aws')) or not os.path.exists('.env')): +# os.system("bash setup.sh") \ No newline at end of file diff --git a/src/config.py b/magemaker/config.py similarity index 82% rename from src/config.py rename to magemaker/config.py index 5689689..9aea006 100644 --- a/src/config.py +++ b/magemaker/config.py @@ -1,19 +1,24 @@ import glob import yaml -from src.yaml import dumper -from src.schemas.model import Model -from src.schemas.deployment import Deployment +from magemaker.yaml import dumper +from magemaker.schemas.model import Model +from magemaker.schemas.deployment import Deployment from typing import Dict, Tuple, List, NamedTuple, Optional +import os + +CONFIG_DIR = os.getenv("CONFIG_DIR", ".magemaker_configs") + +if not os.path.exists(CONFIG_DIR): + os.makedirs(CONFIG_DIR) class ModelDeployment(NamedTuple): deployment: Deployment models: List[Model] - def get_deployment_configs(path: Optional[str] = None) -> List[ModelDeployment]: if path is None: - path = "./configs/*.yaml" + path = CONFIG_DIR + "/*.yaml" configurations = glob.glob(path) configs = [] @@ -56,7 +61,7 @@ def get_config_for_endpoint(endpoint_name: str) -> Optional[ModelDeployment]: def write_config(deployment: Deployment, model: Model): - with open(f"./configs/{deployment.endpoint_name}.yaml", 'w') as config: + with open(f"{CONFIG_DIR}/{deployment.endpoint_name}.yaml", 'w') as config: out = { "deployment": deployment, "models": [model], diff --git a/src/console.py b/magemaker/console.py similarity index 100% rename from src/console.py rename to magemaker/console.py diff --git a/src/huggingface/__init__.py b/magemaker/huggingface/__init__.py similarity index 100% rename from src/huggingface/__init__.py rename to magemaker/huggingface/__init__.py diff --git a/src/huggingface/hf_hub_api.py b/magemaker/huggingface/hf_hub_api.py similarity index 79% rename from src/huggingface/hf_hub_api.py rename to magemaker/huggingface/hf_hub_api.py index b30fac6..585eb2c 100644 --- a/src/huggingface/hf_hub_api.py +++ b/magemaker/huggingface/hf_hub_api.py @@ -1,8 +1,8 @@ from dotenv import dotenv_values -from src.console import console -from src.huggingface import hf_api -from src.schemas.model import Model -from src.utils.rich_utils import print_error +from magemaker.console import console +from magemaker.huggingface import hf_api +from magemaker.schemas.model import Model +from magemaker.utils.rich_utils import print_error HUGGING_FACE_HUB_TOKEN = dotenv_values(".env").get("HUGGING_FACE_HUB_KEY") diff --git a/src/main.py b/magemaker/main.py similarity index 86% rename from src/main.py rename to magemaker/main.py index 93e39f6..5aa811b 100644 --- a/src/main.py +++ b/magemaker/main.py @@ -2,17 +2,17 @@ import logging import threading from InquirerPy import prompt -from src.sagemaker import EC2Instance -from src.sagemaker.create_model import deploy_model -from src.sagemaker.delete_model import delete_sagemaker_model -from src.sagemaker.resources import list_sagemaker_endpoints, select_instance, list_service_quotas_async -from src.sagemaker.query_endpoint import make_query_request -from src.sagemaker.search_jumpstart_models import search_sagemaker_jumpstart_model -from src.utils.rich_utils import print_error, print_success -from src.schemas.deployment import Deployment, Destination -from src.schemas.model import Model, ModelSource -from src.schemas.query import Query -from src.config import get_config_for_endpoint +from magemaker.sagemaker import EC2Instance +from magemaker.sagemaker.create_model import deploy_model +from magemaker.sagemaker.delete_model import delete_sagemaker_model +from magemaker.sagemaker.resources import list_sagemaker_endpoints, select_instance, list_service_quotas_async +from magemaker.sagemaker.query_endpoint import make_query_request +from magemaker.sagemaker.search_jumpstart_models import search_sagemaker_jumpstart_model +from magemaker.utils.rich_utils import print_error, print_success +from magemaker.schemas.deployment import Deployment, Destination +from magemaker.schemas.model import Model, ModelSource +from magemaker.schemas.query import Query +from magemaker.config import get_config_for_endpoint from enum import StrEnum from rich import print @@ -23,15 +23,18 @@ class Actions(StrEnum): DELETE = "Delete a model endpoint" QUERY = "Query a model endpoint" EXIT = "Quit" - # TRAIN = "fine tune a model" + TRAIN = "fine tune a model" +import os -def main(args, loglevel): - logging.basicConfig(format="%(levelname)s: %(message)s", level=loglevel) +# set AWS_REGION in env +os.environ["AWS_REGION"] = "us-west-2" - print("[magenta]Model Manager by OpenFoundry.") - print("[magenta]Star us on Github ☆! [blue]https://github.com/openfoundry-ai/model_manager") +def main(args=None, loglevel='INFO'): + logging.basicConfig(format="%(levelname)s: %(message)s", level=loglevel) + print("[magenta]Magemaker by SlashML") + # list_service_quotas is a pretty slow API and it's paginated. # Use async here and store the result in instances instances = [] @@ -109,8 +112,12 @@ def main(args, loglevel): config = get_config_for_endpoint(endpoint) # support multi-model endpoints - config = (config.deployment, config.models[0]) - make_query_request(endpoint, query, config) + if config: + config = (config.deployment, config.models[0]) + make_query_request(endpoint, query, config) + + print('Config for this model not found, try another model') + case Actions.EXIT: quit() diff --git a/magemaker/runner.py b/magemaker/runner.py new file mode 100644 index 0000000..0c54f1a --- /dev/null +++ b/magemaker/runner.py @@ -0,0 +1,175 @@ +import argparse +import logging +import traceback +import yaml +logging.getLogger("sagemaker.config").setLevel(logging.WARNING) +logging.getLogger("botocore.credentials").setLevel(logging.WARNING) +import os +from magemaker.sagemaker.create_model import deploy_huggingface_model, deploy_model +from magemaker.sagemaker.fine_tune_model import fine_tune_model +from magemaker.schemas.deployment import Deployment +from magemaker.schemas.model import Model + + +def runner(): + if (not os.path.exists(os.path.expanduser('~/.aws')) or not os.path.exists('.env')): + os.system("bash setup.sh") + + parser = argparse.ArgumentParser( + description="Create, deploy, query against models.", + epilog="As an alternative to the commandline, params can be placed in a file, one per line, and specified on the commandline like '%(prog)s @params.conf'.", + fromfile_prefix_chars='@') + parser.add_argument( + "--hf", + help="Deploy a Hugging Face Model.", + type=str + ) + parser.add_argument( + "--instance", + help="EC2 instance type to deploy to.", + type=str + ) + parser.add_argument( + "--deploy", + help="path to YAML deployment configuration file", + type=str + ) + parser.add_argument( + "--train", + help="path to YAML training configuration file", + type=str + ) + parser.add_argument( + "-v", + "--verbose", + help="increase output verbosity", + action="store_true") + args = parser.parse_args() + + # Setup logging + if args.verbose: + loglevel = logging.DEBUG + else: + loglevel = logging.INFO + + if args.hf is not None: + instance_type = args.instance or "ml.m5.xlarge" + predictor = deploy_huggingface_model(args.hf, instance_type) + quit() + + if args.deploy is not None: + try: + deployment = None + model = None + with open(args.deploy) as config: + configuration = yaml.safe_load(config) + deployment = configuration['deployment'] + + # TODO: Support multi-model endpoints + model = configuration['models'][0] + deploy_model(deployment, model) + except: + traceback.print_exc() + print("File not found") + + quit() + + if args.train is not None: + try: + train = None + model = None + with open(args.train) as config: + configuration = yaml.safe_load(config) + training = configuration['training'] + model = configuration['models'][0] + fine_tune_model(training, model) + except: + traceback.print_exc() + print("File not found") + + quit() + + from magemaker.main import main + main(args, loglevel) + +if __name__ == '__main__': + # Run setup if these files/directories don't already exist + if (not os.path.exists(os.path.expanduser('~/.aws')) or not os.path.exists('.env')): + os.system("bash setup.sh") + + parser = argparse.ArgumentParser( + description="Create, deploy, query against models.", + epilog="As an alternative to the commandline, params can be placed in a file, one per line, and specified on the commandline like '%(prog)s @params.conf'.", + fromfile_prefix_chars='@') + parser.add_argument( + "--hf", + help="Deploy a Hugging Face Model.", + type=str + ) + parser.add_argument( + "--instance", + help="EC2 instance type to deploy to.", + type=str + ) + parser.add_argument( + "--deploy", + help="path to YAML deployment configuration file", + type=str + ) + parser.add_argument( + "--train", + help="path to YAML training configuration file", + type=str + ) + parser.add_argument( + "-v", + "--verbose", + help="increase output verbosity", + action="store_true") + args = parser.parse_args() + + # Setup logging + if args.verbose: + loglevel = logging.DEBUG + else: + loglevel = logging.INFO + + if args.hf is not None: + instance_type = args.instance or "ml.m5.xlarge" + predictor = deploy_huggingface_model(args.hf, instance_type) + quit() + + if args.deploy is not None: + try: + deployment = None + model = None + with open(args.deploy) as config: + configuration = yaml.safe_load(config) + deployment = configuration['deployment'] + + # TODO: Support multi-model endpoints + model = configuration['models'][0] + deploy_model(deployment, model) + except: + traceback.print_exc() + print("File not found") + + quit() + + if args.train is not None: + try: + train = None + model = None + with open(args.train) as config: + configuration = yaml.safe_load(config) + training = configuration['training'] + model = configuration['models'][0] + fine_tune_model(training, model) + except: + traceback.print_exc() + print("File not found") + + quit() + + from magemaker.main import main + main(args, loglevel) diff --git a/src/sagemaker/__init__.py b/magemaker/sagemaker/__init__.py similarity index 100% rename from src/sagemaker/__init__.py rename to magemaker/sagemaker/__init__.py diff --git a/src/sagemaker/create_model.py b/magemaker/sagemaker/create_model.py similarity index 93% rename from src/sagemaker/create_model.py rename to magemaker/sagemaker/create_model.py index da71ae2..685cf17 100644 --- a/src/sagemaker/create_model.py +++ b/magemaker/sagemaker/create_model.py @@ -9,16 +9,16 @@ from sagemaker.model import Model from sagemaker.predictor import Predictor from sagemaker.s3 import S3Uploader -from src.config import write_config -from src.schemas.model import Model, ModelSource -from src.schemas.deployment import Deployment -from src.session import session, sagemaker_session -from src.console import console -from src.utils.aws_utils import construct_s3_uri, is_s3_uri -from src.utils.rich_utils import print_error, print_success -from src.utils.model_utils import get_unique_endpoint_name, get_model_and_task -from src.huggingface import HuggingFaceTask -from src.huggingface.hf_hub_api import get_hf_task +from magemaker.config import write_config +from magemaker.schemas.model import Model, ModelSource +from magemaker.schemas.deployment import Deployment +from magemaker.session import session, sagemaker_session +from magemaker.console import console +from magemaker.utils.aws_utils import construct_s3_uri, is_s3_uri +from magemaker.utils.rich_utils import print_error, print_success +from magemaker.utils.model_utils import get_unique_endpoint_name, get_model_and_task +from magemaker.huggingface import HuggingFaceTask +from magemaker.huggingface.hf_hub_api import get_hf_task HUGGING_FACE_HUB_TOKEN = dotenv_values(".env").get("HUGGING_FACE_HUB_KEY") SAGEMAKER_ROLE = dotenv_values(".env")["SAGEMAKER_ROLE"] diff --git a/src/sagemaker/delete_model.py b/magemaker/sagemaker/delete_model.py similarity index 89% rename from src/sagemaker/delete_model.py rename to magemaker/sagemaker/delete_model.py index 7bc11ad..7c10078 100644 --- a/src/sagemaker/delete_model.py +++ b/magemaker/sagemaker/delete_model.py @@ -1,6 +1,6 @@ import boto3 from rich import print -from src.utils.rich_utils import print_success +from magemaker.utils.rich_utils import print_success from typing import List diff --git a/src/sagemaker/fine_tune_model.py b/magemaker/sagemaker/fine_tune_model.py similarity index 93% rename from src/sagemaker/fine_tune_model.py rename to magemaker/sagemaker/fine_tune_model.py index 7960a3d..2572f6a 100644 --- a/src/sagemaker/fine_tune_model.py +++ b/magemaker/sagemaker/fine_tune_model.py @@ -6,12 +6,12 @@ from rich import print from rich.table import Table from sagemaker.jumpstart.estimator import JumpStartEstimator -from src.console import console -from src.schemas.model import Model, ModelSource -from src.schemas.training import Training -from src.session import sagemaker_session -from src.utils.aws_utils import is_s3_uri -from src.utils.rich_utils import print_success, print_error +from magemaker.console import console +from magemaker.schemas.model import Model, ModelSource +from magemaker.schemas.training import Training +from magemaker.session import sagemaker_session +from magemaker.utils.aws_utils import is_s3_uri +from magemaker.utils.rich_utils import print_success, print_error from transformers import AutoTokenizer from dotenv import load_dotenv diff --git a/src/sagemaker/query_endpoint.py b/magemaker/sagemaker/query_endpoint.py similarity index 93% rename from src/sagemaker/query_endpoint.py rename to magemaker/sagemaker/query_endpoint.py index 0bcddc8..8c425a4 100644 --- a/src/sagemaker/query_endpoint.py +++ b/magemaker/sagemaker/query_endpoint.py @@ -3,16 +3,16 @@ import inquirer from InquirerPy import prompt from sagemaker.huggingface.model import HuggingFacePredictor -from src.config import ModelDeployment -from src.console import console -from src.sagemaker import SagemakerTask -from src.huggingface import HuggingFaceTask -from src.utils.model_utils import get_model_and_task, is_sagemaker_model, get_text_generation_hyperpameters -from src.utils.rich_utils import print_error -from src.schemas.deployment import Deployment -from src.schemas.model import Model -from src.schemas.query import Query -from src.session import sagemaker_session +from magemaker.config import ModelDeployment +from magemaker.console import console +from magemaker.sagemaker import SagemakerTask +from magemaker.huggingface import HuggingFaceTask +from magemaker.utils.model_utils import get_model_and_task, is_sagemaker_model, get_text_generation_hyperpameters +from magemaker.utils.rich_utils import print_error +from magemaker.schemas.deployment import Deployment +from magemaker.schemas.model import Model +from magemaker.schemas.query import Query +from magemaker.session import sagemaker_session from typing import Dict, Tuple, Optional diff --git a/src/sagemaker/resources.py b/magemaker/sagemaker/resources.py similarity index 94% rename from src/sagemaker/resources.py rename to magemaker/sagemaker/resources.py index 85ab434..a2bea87 100644 --- a/src/sagemaker/resources.py +++ b/magemaker/sagemaker/resources.py @@ -1,10 +1,10 @@ import boto3 from functools import lru_cache from InquirerPy import inquirer -from src.console import console -from src.sagemaker import EC2Instance -from src.config import get_config_for_endpoint -from src.utils.format import format_sagemaker_endpoint, format_python_dict +from magemaker.console import console +from magemaker.sagemaker import EC2Instance +from magemaker.config import get_config_for_endpoint +from magemaker.utils.format import format_sagemaker_endpoint, format_python_dict from typing import List, Tuple, Dict, Optional diff --git a/src/sagemaker/search_jumpstart_models.py b/magemaker/sagemaker/search_jumpstart_models.py similarity index 89% rename from src/sagemaker/search_jumpstart_models.py rename to magemaker/sagemaker/search_jumpstart_models.py index 3d1f658..6830d42 100644 --- a/src/sagemaker/search_jumpstart_models.py +++ b/magemaker/sagemaker/search_jumpstart_models.py @@ -1,8 +1,8 @@ import inquirer from enum import StrEnum, auto from sagemaker.jumpstart.notebook_utils import list_jumpstart_models -from src.utils.rich_utils import print_error -from src.session import session, sagemaker_session +from magemaker.utils.rich_utils import print_error +from magemaker.session import session, sagemaker_session class Frameworks(StrEnum): diff --git a/magemaker/schemas/__init__.py b/magemaker/schemas/__init__.py new file mode 100644 index 0000000..9b6e0b8 --- /dev/null +++ b/magemaker/schemas/__init__.py @@ -0,0 +1,4 @@ +import magemaker.schemas.deployment +import magemaker.schemas.model +import magemaker.schemas.query +import magemaker.schemas.training diff --git a/src/schemas/deployment.py b/magemaker/schemas/deployment.py similarity index 96% rename from src/schemas/deployment.py rename to magemaker/schemas/deployment.py index e0647d2..accbee6 100644 --- a/src/schemas/deployment.py +++ b/magemaker/schemas/deployment.py @@ -1,5 +1,5 @@ import yaml -from src.yaml import loader, dumper +from magemaker.yaml import loader, dumper from typing import Optional from enum import StrEnum from pydantic import BaseModel diff --git a/src/schemas/model.py b/magemaker/schemas/model.py similarity index 88% rename from src/schemas/model.py rename to magemaker/schemas/model.py index b49e9c0..c274046 100644 --- a/src/schemas/model.py +++ b/magemaker/schemas/model.py @@ -1,9 +1,9 @@ import yaml -from src.yaml import loader, dumper +from magemaker.yaml import loader, dumper from typing import Optional, Union, Dict from enum import StrEnum -from src.huggingface import HuggingFaceTask -from src.sagemaker import SagemakerTask +from magemaker.huggingface import HuggingFaceTask +from magemaker.sagemaker import SagemakerTask from pydantic import BaseModel diff --git a/src/schemas/query.py b/magemaker/schemas/query.py similarity index 100% rename from src/schemas/query.py rename to magemaker/schemas/query.py diff --git a/src/schemas/training.py b/magemaker/schemas/training.py similarity index 93% rename from src/schemas/training.py rename to magemaker/schemas/training.py index ae1030d..f60a15f 100644 --- a/src/schemas/training.py +++ b/magemaker/schemas/training.py @@ -1,8 +1,8 @@ import yaml from pydantic import BaseModel from typing import Optional -from src.schemas.deployment import Destination -from src.yaml import loader, dumper +from magemaker.schemas.deployment import Destination +from magemaker.yaml import loader, dumper class Hyperparameters(BaseModel): diff --git a/magemaker/scripts/preflight.sh b/magemaker/scripts/preflight.sh new file mode 100755 index 0000000..a20e503 --- /dev/null +++ b/magemaker/scripts/preflight.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +# Get the directory where the script is located +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + + +echo "you need to create an aws use with access to Sagemaker" +echo "if you don't know how to do that follow this doc https://docs.google.com/document/d/1NvA6uZmppsYzaOdkcgNTRl7Nb4LbpP9Koc4H_t5xNSg/edit?usp=sharing" + + +if ! command -v aws &> /dev/null +then + OS="$(uname -s)" + case "${OS}" in + Linux*) + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" + unzip awscliv2.zip + sudo ./aws/install + ;; + Darwin*) + curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg" + sudo installer -pkg AWSCLIV2.pkg -target / + ;; + *) + echo "Unsupported OS: ${OS}. See https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html" + exit 1 + ;; + esac +fi +aws configure set region us-east-1 && aws configure +touch .env + + +if ! grep -q "SAGEMAKER_ROLE" .env +then + # bash ./setup_role.sh + bash "$SCRIPT_DIR/setup_role.sh" +fi \ No newline at end of file diff --git a/scripts/setup_role.sh b/magemaker/scripts/setup_role.sh old mode 100644 new mode 100755 similarity index 100% rename from scripts/setup_role.sh rename to magemaker/scripts/setup_role.sh diff --git a/src/session.py b/magemaker/session.py similarity index 100% rename from src/session.py rename to magemaker/session.py diff --git a/src/__init__.py b/magemaker/utils/__init__.py similarity index 100% rename from src/__init__.py rename to magemaker/utils/__init__.py diff --git a/src/utils/aws_utils.py b/magemaker/utils/aws_utils.py similarity index 100% rename from src/utils/aws_utils.py rename to magemaker/utils/aws_utils.py diff --git a/src/utils/format.py b/magemaker/utils/format.py similarity index 100% rename from src/utils/format.py rename to magemaker/utils/format.py diff --git a/src/utils/model_utils.py b/magemaker/utils/model_utils.py similarity index 92% rename from src/utils/model_utils.py rename to magemaker/utils/model_utils.py index cbe3018..f93a5d9 100644 --- a/src/utils/model_utils.py +++ b/magemaker/utils/model_utils.py @@ -2,12 +2,12 @@ from difflib import SequenceMatcher from dotenv import dotenv_values from huggingface_hub import HfApi -from src.utils.rich_utils import print_error -from src.sagemaker import SagemakerTask -from src.schemas.deployment import Deployment -from src.schemas.model import Model, ModelSource -from src.schemas.query import Query -from src.session import sagemaker_session +from magemaker.utils.rich_utils import print_error +from magemaker.sagemaker import SagemakerTask +from magemaker.schemas.deployment import Deployment +from magemaker.schemas.model import Model, ModelSource +from magemaker.schemas.query import Query +from magemaker.session import sagemaker_session from typing import Dict, Tuple, Optional HUGGING_FACE_HUB_TOKEN = dotenv_values(".env").get("HUGGING_FACE_HUB_KEY") diff --git a/src/utils/rich_utils.py b/magemaker/utils/rich_utils.py similarity index 100% rename from src/utils/rich_utils.py rename to magemaker/utils/rich_utils.py diff --git a/src/yaml.py b/magemaker/yaml.py similarity index 100% rename from src/yaml.py rename to magemaker/yaml.py diff --git a/model_manager.py b/model_manager.py deleted file mode 100644 index a7d3a7d..0000000 --- a/model_manager.py +++ /dev/null @@ -1,94 +0,0 @@ -import argparse -import logging -import traceback -import yaml -logging.getLogger("sagemaker.config").setLevel(logging.WARNING) -logging.getLogger("botocore.credentials").setLevel(logging.WARNING) -import os -from src.sagemaker.create_model import deploy_huggingface_model, deploy_model -from src.sagemaker.fine_tune_model import fine_tune_model -from src.schemas.deployment import Deployment -from src.schemas.model import Model - - -if __name__ == '__main__': - # Run setup if these files/directories don't already exist - if (not os.path.exists(os.path.expanduser('~/.aws')) or not os.path.exists('.env')): - os.system("bash setup.sh") - - parser = argparse.ArgumentParser( - description="Create, deploy, query against models.", - epilog="As an alternative to the commandline, params can be placed in a file, one per line, and specified on the commandline like '%(prog)s @params.conf'.", - fromfile_prefix_chars='@') - parser.add_argument( - "--hf", - help="Deploy a Hugging Face Model.", - type=str - ) - parser.add_argument( - "--instance", - help="EC2 instance type to deploy to.", - type=str - ) - parser.add_argument( - "--deploy", - help="path to YAML deployment configuration file", - type=str - ) - parser.add_argument( - "--train", - help="path to YAML training configuration file", - type=str - ) - parser.add_argument( - "-v", - "--verbose", - help="increase output verbosity", - action="store_true") - args = parser.parse_args() - - # Setup logging - if args.verbose: - loglevel = logging.DEBUG - else: - loglevel = logging.INFO - - if args.hf is not None: - instance_type = args.instance or "ml.m5.xlarge" - predictor = deploy_huggingface_model(args.hf, instance_type) - quit() - - if args.deploy is not None: - try: - deployment = None - model = None - with open(args.deploy) as config: - configuration = yaml.safe_load(config) - deployment = configuration['deployment'] - - # TODO: Support multi-model endpoints - model = configuration['models'][0] - deploy_model(deployment, model) - except: - traceback.print_exc() - print("File not found") - - quit() - - if args.train is not None: - try: - train = None - model = None - with open(args.train) as config: - configuration = yaml.safe_load(config) - training = configuration['training'] - model = configuration['models'][0] - fine_tune_model(training, model) - except: - traceback.print_exc() - print("File not found") - - quit() - - from src.main import main - main(args, loglevel) diff --git a/pyproject.toml b/pyproject.toml index ff23b23..a737be4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,9 @@ [project] -name = "model_manager" -version = "0.1.0" +name = "magemaker" +version = "0.1.1" description = "Default template for PDM package" authors = [ - {name = "Arthur Chi", email = "arthur@openfoundry.ai"}, + {name = "eff-kay", email = "faizank@slashml.com"}, ] dependencies = [ "pyyaml>=6.0.1", @@ -22,16 +22,26 @@ dependencies = [ "fastapi>=0.111.0", "litellm>=1.37.5", ] -requires-python = ">=3.12" +requires-python = ">=3.11" readme = "README.md" license = {text = "MIT"} + +[project.scripts] +magemaker = "magemaker.runner:runner" + + [build-system] requires = ["pdm-backend"] build-backend = "pdm.backend" [tool.pdm] distribution = true +package-dir = "magemaker" + +[tool.pdm.build] +includes = ["magemaker", "magemaker/scripts/preflight.sh", "magemaker/scripts/setup_role.sh"] # Include setup.sh in the package distribution + [tool.pdm.dev-dependencies] test = [ diff --git a/server.py b/server.py index 8ffb950..03edcc2 100644 --- a/server.py +++ b/server.py @@ -2,11 +2,11 @@ import os from dotenv import dotenv_values from fastapi import FastAPI -from src.config import get_config_for_endpoint, get_endpoints_for_model -from src.sagemaker.resources import get_sagemaker_endpoint -from src.sagemaker.query_endpoint import make_query_request -from src.schemas.query import Query, ChatCompletion -from src.session import session +from magemaker.config import get_config_for_endpoint, get_endpoints_for_model +from magemaker.sagemaker.resources import get_sagemaker_endpoint +from magemaker.sagemaker.query_endpoint import make_query_request +from magemaker.schemas.query import Query, ChatCompletion +from magemaker.session import session from litellm import completion os.environ["AWS_REGION_NAME"] = session.region_name diff --git a/src/schemas/__init__.py b/src/schemas/__init__.py deleted file mode 100644 index 47ff19f..0000000 --- a/src/schemas/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -import src.schemas.deployment -import src.schemas.model -import src.schemas.query -import src.schemas.training diff --git a/src/utils/__init__.py b/src/utils/__init__.py deleted file mode 100644 index e69de29..0000000