From 86149d4c630700f12ff653ba9d99f101468df052 Mon Sep 17 00:00:00 2001 From: Addie Rudy Date: Mon, 25 Nov 2024 10:05:39 -0500 Subject: [PATCH] refactor: Main Project + Python POCs now managed by Projen POCs are now managed using Projen to create and update POC structure. To create a new POC, please follow the updated CONTRIBUTING.md guide. --- .eslintrc.json | 235 + .gitattributes | 17 + .gitignore | 264 +- .npmignore | 21 + .projen/deps.json | 62 + .projen/files.json | 16 + .projen/tasks.json | 247 + .projenrc.ts | 1901 +++++ CONTRIBUTING.md | 41 + LICENSE | 218 +- README.md | 373 +- ...zon.Bedrock.Document.Ggenerator.Poc.csproj | 0 .../Components/App.razor | 0 .../Components/Layout/MainLayout.razor | 0 .../Components/Layout/NavMenu.razor | 0 .../Pages/DocumentGeneratorForm.razor | 0 .../Components/Pages/Home.razor | 0 .../Components/Routes.razor | 0 .../Components/_Imports.razor | 0 .../Data/01-doc-template.txt | 0 .../LICENSE | 0 .../Program.cs | 0 .../Properties/launchSettings.json | 0 .../Readme.md | 0 .../appsettings.Development.json | 0 .../appsettings.json | 0 .../images/01-document-generator.png | Bin .../images/architecture.png | Bin .../images/demo.gif | Bin .../wwwroot/app.css | 0 .../wwwroot/favicon.ico | Bin .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 56 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 77 +- .../requirements-dev.txt | 2 + .../requirements.txt | 20 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../amazon-bedrock-amazon-athena-poc/HOWTO.md | 7 + .../README.md | 140 +- .../requirements-dev.txt | 2 + .../requirements.txt | 118 +- .../.gitattributes | 12 + .../amazon-bedrock-amazon-rds-poc/.gitignore | 85 + .../.projen/deps.json | 39 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../amazon-bedrock-amazon-rds-poc/HOWTO.md | 7 + .../amazon-bedrock-amazon-rds-poc/README.md | 134 +- .../requirements-dev.txt | 2 + .../requirements.txt | 129 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 39 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 145 +- .../requirements-dev.txt | 2 + .../requirements.txt | 130 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 39 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 149 +- .../requirements-dev.txt | 2 + .../requirements.txt | 67 +- .../amazon-bedrock-chat-poc/.gitattributes | 12 + .../amazon-bedrock-chat-poc/.gitignore | 85 + .../amazon-bedrock-chat-poc/.projen/deps.json | 39 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../amazon-bedrock-chat-poc/HOWTO.md | 7 + .../amazon-bedrock-chat-poc/README.md | 136 +- .../amazon-bedrock-chat-poc/chat_history.txt | 0 .../requirements-dev.txt | 2 + .../amazon-bedrock-chat-poc/requirements.txt | 130 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 39 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 124 +- .../requirements-dev.txt | 2 + .../requirements.txt | 60 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 30 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 121 +- .../requirements-dev.txt | 2 + .../requirements.txt | 11 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 30 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 113 +- .../requirements-dev.txt | 2 + .../requirements.txt | 58 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 111 +- .../requirements-dev.txt | 2 + .../requirements.txt | 57 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../amazon-bedrock-converse-api-poc/HOWTO.md | 7 + .../amazon-bedrock-converse-api-poc/README.md | 116 +- .../requirements-dev.txt | 2 + .../requirements.txt | 9 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 109 +- .../requirements-dev.txt | 2 + .../requirements.txt | 8 +- .../.gitattributes | 12 + .../amazon-bedrock-csv-chatbot-poc/.gitignore | 85 + .../.projen/deps.json | 30 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../amazon-bedrock-csv-chatbot-poc/HOWTO.md | 7 + .../amazon-bedrock-csv-chatbot-poc/README.md | 130 +- .../requirements-dev.txt | 2 + .../requirements.txt | 89 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 43 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 186 +- .../requirements-dev.txt | 2 + .../requirements.txt | 134 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 268 +- .../requirements-dev.txt | 2 + .../requirements.txt | 57 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 39 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 196 +- .../requirements-dev.txt | 2 + .../requirements.txt | 130 +- .../.gitattributes | 12 + .../amazon-bedrock-guardrails-poc/.gitignore | 85 + .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../amazon-bedrock-guardrails-poc/HOWTO.md | 7 + .../amazon-bedrock-guardrails-poc/README.md | 113 +- .../requirements-dev.txt | 2 + .../requirements.txt | 8 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 30 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 105 +- .../requirements-dev.txt | 2 + .../requirements.txt | 64 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 106 +- .../image_generation_guardrails.py | 2 +- ...nerateImageWithGuardrails.gif => demo.gif} | Bin .../requirements-dev.txt | 2 + .../requirements.txt | 8 +- .../.gitattributes | 12 + .../.gitignore | 103 +- .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 181 +- .../requirements-dev.txt | 2 + .../requirements.txt | 88 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 191 +- .../requirements-dev.txt | 2 + .../requirements.txt | 9 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 39 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../amazon-bedrock-langchain-rag-poc/HOWTO.md | 7 + .../README.md | 160 +- .../requirements-dev.txt | 2 + .../requirements.txt | 14 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 30 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 122 +- .../requirements-dev.txt | 2 + .../requirements.txt | 10 +- .../.gitattributes | 11 + .../.gitignore | 84 + .../.projen/deps.json | 26 + .../.projen/files.json | 12 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../requirements-dev.txt | 2 + .../requirements.txt | 5 + .../.gitattributes | 12 + .../amazon-bedrock-model-eval-poc/.gitignore | 85 + .../.projen/deps.json | 34 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../amazon-bedrock-model-eval-poc/HOWTO.md | 33 + .../amazon-bedrock-model-eval-poc/README.md | 116 +- .../requirements-dev.txt | 2 + .../requirements.txt | 10 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 110 +- .../requirements-dev.txt | 2 + .../requirements.txt | 53 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 59 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../README.md | 14 +- .../requirements-dev.txt | 2 + .../requirements.txt | 5 +- .../.gitattributes | 12 + .../amazon-bedrock-rag-kendra-poc/.gitignore | 85 + .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../amazon-bedrock-rag-kendra-poc/HOWTO.md | 7 + .../amazon-bedrock-rag-kendra-poc/README.md | 227 +- ...-rag-architecture.png => architecture.png} | Bin .../requirements-dev.txt | 2 + .../requirements.txt | 63 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 43 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 279 +- .../requirements-dev.txt | 2 + .../requirements.txt | 90 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 30 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 190 +- .../app.py | 5 + .../architecture.png} | Bin .../SemanticCache.gif => images/demo.gif} | Bin .../{image => images}/os-permissions-1.png | Bin .../{image => images}/os-permissions-2.png | Bin .../{image => images}/os-permissions-3.png | Bin .../{image => images}/os-permissions-4.png | Bin .../{image => images}/os-permissions-5.png | Bin .../{image => images}/os-permissions-6.png | Bin .../requirements-dev.txt | 2 + .../requirements.txt | 11 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 47 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 209 +- .../requirements-dev.txt | 2 + .../requirements.txt | 134 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 145 +- .../requirements-dev.txt | 2 + .../requirements.txt | 57 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 43 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 163 +- .../requirements-dev.txt | 2 + .../requirements.txt | 92 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 118 +- .../images/architecture.jpg | Bin 0 -> 58497 bytes .../{public => images}/demo.gif | Bin .../requirements-dev.txt | 2 + .../requirements.txt | 9 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 30 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 130 +- .../requirements-dev.txt | 2 + .../requirements.txt | 11 +- .../.gitattributes | 12 + .../amazon-bedrock-translation-poc/.gitignore | 85 + .../.projen/deps.json | 26 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../amazon-bedrock-translation-poc/HOWTO.md | 7 + .../amazon-bedrock-translation-poc/README.md | 206 +- .../amazon-bedrock-translation-poc/app.py | 5 + .../requirements-dev.txt | 2 + .../requirements.txt | 8 +- .../.gitattributes | 12 + .../.gitignore | 85 + .../.projen/deps.json | 43 + .../.projen/files.json | 13 + .../.projen/tasks.json | 80 + .../HOWTO.md | 7 + .../README.md | 146 +- .../images/architecture.png | Bin 0 -> 119756 bytes .../requirements-dev.txt | 2 + .../requirements.txt | 17 +- package-lock.json | 6789 +++++++++++++++++ package.json | 51 + projenrc/projects/core-readme-component.ts | 30 + projenrc/projects/dot-net-quickstart-pocs.ts | 12 + projenrc/projects/resources/root-readme.md | 64 + projenrc/projects/resources/streamlit-app.py | 5 + .../projects/resources/streamlit-howto.md | 7 + .../projects/resources/streamlit-readme.md | 81 + projenrc/projects/resources/types.ts | 6 + projenrc/projects/streamlit-quickstart-poc.ts | 156 + src/index.ts | 5 + test/hello.test.ts | 5 + tsconfig.dev.json | 41 + tsconfig.json | 37 + 393 files changed, 21526 insertions(+), 5067 deletions(-) create mode 100644 .eslintrc.json create mode 100644 .gitattributes create mode 100644 .npmignore create mode 100644 .projen/deps.json create mode 100644 .projen/files.json create mode 100644 .projen/tasks.json create mode 100644 .projenrc.ts rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/Amazon.Bedrock.Document.Ggenerator.Poc.csproj (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/Components/App.razor (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/Components/Layout/MainLayout.razor (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/Components/Layout/NavMenu.razor (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/Components/Pages/DocumentGeneratorForm.razor (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/Components/Pages/Home.razor (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/Components/Routes.razor (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/Components/_Imports.razor (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/Data/01-doc-template.txt (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/LICENSE (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/Program.cs (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/Properties/launchSettings.json (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/Readme.md (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/appsettings.Development.json (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/appsettings.json (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/images/01-document-generator.png (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/images/architecture.png (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/images/demo.gif (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/wwwroot/app.css (100%) rename genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/{Amazon.Bedrock.Document.Ggenerator.Poc => Amazon.Bedrock.Document.Generator.Poc}/wwwroot/favicon.ico (100%) create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-chat-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-chat-poc/chat_history.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-chat-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/HOWTO.md rename genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/images/{GenerateImageWithGuardrails.gif => demo.gif} (100%) create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-customization/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-customization/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-customization/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-customization/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-customization/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-customization/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-customization/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-customization/requirements.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/HOWTO.md rename genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/images/{kendra-rag-architecture.png => architecture.png} (100%) create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/app.py rename genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/{image/semantic-cache-architecture.png => images/architecture.png} (100%) rename genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/{image/SemanticCache.gif => images/demo.gif} (100%) rename genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/{image => images}/os-permissions-1.png (100%) rename genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/{image => images}/os-permissions-2.png (100%) rename genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/{image => images}/os-permissions-3.png (100%) rename genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/{image => images}/os-permissions-4.png (100%) rename genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/{image => images}/os-permissions-5.png (100%) rename genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/{image => images}/os-permissions-6.png (100%) create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-task-classification/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-task-classification/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-task-classification/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-task-classification/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-task-classification/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-task-classification/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-task-classification/images/architecture.jpg rename genai-quickstart-pocs-python/amazon-bedrock-task-classification/{public => images}/demo.gif (100%) create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-task-classification/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-translation-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-translation-poc/app.py create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-translation-poc/requirements-dev.txt create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.gitattributes create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.gitignore create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.projen/deps.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.projen/files.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.projen/tasks.json create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/HOWTO.md create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/images/architecture.png create mode 100644 genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/requirements-dev.txt create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 projenrc/projects/core-readme-component.ts create mode 100644 projenrc/projects/dot-net-quickstart-pocs.ts create mode 100644 projenrc/projects/resources/root-readme.md create mode 100644 projenrc/projects/resources/streamlit-app.py create mode 100644 projenrc/projects/resources/streamlit-howto.md create mode 100644 projenrc/projects/resources/streamlit-readme.md create mode 100644 projenrc/projects/resources/types.ts create mode 100644 projenrc/projects/streamlit-quickstart-poc.ts create mode 100644 src/index.ts create mode 100644 test/hello.test.ts create mode 100644 tsconfig.dev.json create mode 100644 tsconfig.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..3eb5f2bc --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,235 @@ +// ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". +{ + "env": { + "jest": true, + "node": true + }, + "root": true, + "plugins": [ + "@typescript-eslint", + "import" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module", + "project": "./tsconfig.dev.json" + }, + "extends": [ + "plugin:import/typescript" + ], + "settings": { + "import/parsers": { + "@typescript-eslint/parser": [ + ".ts", + ".tsx" + ] + }, + "import/resolver": { + "node": {}, + "typescript": { + "project": "./tsconfig.dev.json", + "alwaysTryTypes": true + } + } + }, + "ignorePatterns": [ + "*.js", + "*.d.ts", + "node_modules/", + "*.generated.ts", + "coverage", + "!.projenrc.ts", + "!projenrc/**/*.ts" + ], + "rules": { + "indent": [ + "off" + ], + "@typescript-eslint/indent": [ + "error", + 2 + ], + "quotes": [ + "error", + "single", + { + "avoidEscape": true + } + ], + "comma-dangle": [ + "error", + "always-multiline" + ], + "comma-spacing": [ + "error", + { + "before": false, + "after": true + } + ], + "no-multi-spaces": [ + "error", + { + "ignoreEOLComments": false + } + ], + "array-bracket-spacing": [ + "error", + "never" + ], + "array-bracket-newline": [ + "error", + "consistent" + ], + "object-curly-spacing": [ + "error", + "always" + ], + "object-curly-newline": [ + "error", + { + "multiline": true, + "consistent": true + } + ], + "object-property-newline": [ + "error", + { + "allowAllPropertiesOnSameLine": true + } + ], + "keyword-spacing": [ + "error" + ], + "brace-style": [ + "error", + "1tbs", + { + "allowSingleLine": true + } + ], + "space-before-blocks": [ + "error" + ], + "curly": [ + "error", + "multi-line", + "consistent" + ], + "@typescript-eslint/member-delimiter-style": [ + "error" + ], + "semi": [ + "error", + "always" + ], + "max-len": [ + "error", + { + "code": 150, + "ignoreUrls": true, + "ignoreStrings": true, + "ignoreTemplateLiterals": true, + "ignoreComments": true, + "ignoreRegExpLiterals": true + } + ], + "quote-props": [ + "error", + "consistent-as-needed" + ], + "@typescript-eslint/no-require-imports": [ + "error" + ], + "import/no-extraneous-dependencies": [ + "error", + { + "devDependencies": [ + "**/test/**", + "**/build-tools/**", + ".projenrc.ts", + "projenrc/**/*.ts" + ], + "optionalDependencies": false, + "peerDependencies": true + } + ], + "import/no-unresolved": [ + "error" + ], + "import/order": [ + "warn", + { + "groups": [ + "builtin", + "external" + ], + "alphabetize": { + "order": "asc", + "caseInsensitive": true + } + } + ], + "import/no-duplicates": [ + "error" + ], + "no-shadow": [ + "off" + ], + "@typescript-eslint/no-shadow": [ + "error" + ], + "key-spacing": [ + "error" + ], + "no-multiple-empty-lines": [ + "error" + ], + "@typescript-eslint/no-floating-promises": [ + "error" + ], + "no-return-await": [ + "off" + ], + "@typescript-eslint/return-await": [ + "error" + ], + "no-trailing-spaces": [ + "error" + ], + "dot-notation": [ + "error" + ], + "no-bitwise": [ + "error" + ], + "@typescript-eslint/member-ordering": [ + "error", + { + "default": [ + "public-static-field", + "public-static-method", + "protected-static-field", + "protected-static-method", + "private-static-field", + "private-static-method", + "field", + "constructor", + "method" + ] + } + ] + }, + "overrides": [ + { + "files": [ + ".projenrc.ts" + ], + "rules": { + "@typescript-eslint/no-require-imports": "off", + "import/no-extraneous-dependencies": "off" + } + } + ] +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..a2f9bd8a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +# ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". + +* text=auto eol=lf +/.eslintrc.json linguist-generated +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.npmignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/LICENSE linguist-generated +/package-lock.json linguist-generated +/package.json linguist-generated +/README.md linguist-generated +/tsconfig.dev.json linguist-generated +/tsconfig.json linguist-generated \ No newline at end of file diff --git a/.gitignore b/.gitignore index ad8570a0..f4a3c934 100644 --- a/.gitignore +++ b/.gitignore @@ -1,217 +1,51 @@ -.idea/ -__pycache__ -venv/ -.venv/ -.env -chat_history.txt -.vsidx -## Default ignore rules for Visual Studio temporary files, build results, and -## various Visual Studio extensions. - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates -# Used by MonoDevelop/Xamarin Studio -*.userprefs - -# Visual Studio cache files -**/.vs/ -**/.vscode/ -# files ending in .cache can be ignored but but keep track of directories ending in .cache -*.[Cc]ache -!*.[Cc]ache/ - -# Folders containing build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Dd]ebugPS/ -[Rr]elease/ -[Rr]eleases/ -[Rr]eleasePS/ -x64/ -x86/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -**/TestResults/ -**/Temp/ -**/buildlogs/ - -# Output from an ATL Project -dlldata.c - -# Other miscellaneous build outputs -ClientBin/ -node_modules/ -Generated_Code/ -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj +# ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +!/package.json +!/LICENSE +!/.npmignore +logs *.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc -*.mdb -*.apk -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.pfx -*.publishsettings -*.codegen.cs - -# Click-Once directory -publish/ - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -*.pubxml -*.publishproj - -# Microsoft Azure -PublishScripts/ -csx/ -*.build.csdef -ecf/ -rcf/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# DNX -**/*project.lock.json -**/project.lock.json -artifacts/ - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# JetBrains tools -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user -*.dotCover -# used by Rider -.idea/ -*.sln.iml - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# NuGet -*.nupkg -**/packages/* -# this is used an MSBuild target, not recovered by dotnet restore so keep it -!**/packages/build/ -*.nuget.props -*.nuget.targets - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat - -# FAKE - F# Make -.fake/ - -# folder for random files during dev/testing -misc/ - -# ignore mac generated file: -.DS_Store +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json +pids +*.pid +*.seed +*.pid.lock +lib-cov +coverage +*.lcov +.nyc_output +build/Release +node_modules/ +jspm_packages/ +*.tsbuildinfo +.eslintcache +*.tgz +.yarn-integrity +.cache +**/.DS_Store +**/__pycache__/ +.env/ +venv +output/ genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/files/ - -# ignore generated image files: -genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/images/ - +genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/generated-images/ +temp/ +cdk.out +/dist/changelog.md +/dist/version.txt +!/test/ +!/tsconfig.json +!/tsconfig.dev.json +!/src/ +/lib +/dist/ +!/.eslintrc.json +!/README.md +!/.projenrc.ts diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..22825c52 --- /dev/null +++ b/.npmignore @@ -0,0 +1,21 @@ +# ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". +/.projen/ +/dist/changelog.md +/dist/version.txt +/test/ +/tsconfig.dev.json +/src/ +!/lib/ +!/lib/**/*.js +!/lib/**/*.d.ts +dist +/tsconfig.json +/.github/ +/.vscode/ +/.idea/ +/.projenrc.js +tsconfig.tsbuildinfo +/.eslintrc.json +/.gitattributes +/.projenrc.ts +/projenrc diff --git a/.projen/deps.json b/.projen/deps.json new file mode 100644 index 00000000..ecb296e4 --- /dev/null +++ b/.projen/deps.json @@ -0,0 +1,62 @@ +{ + "dependencies": [ + { + "name": "@types/node", + "type": "build" + }, + { + "name": "@types/nunjucks", + "type": "build" + }, + { + "name": "@typescript-eslint/eslint-plugin", + "version": "^7", + "type": "build" + }, + { + "name": "@typescript-eslint/parser", + "version": "^7", + "type": "build" + }, + { + "name": "commit-and-tag-version", + "version": "^12", + "type": "build" + }, + { + "name": "constructs", + "version": "^10.0.0", + "type": "build" + }, + { + "name": "eslint-import-resolver-typescript", + "type": "build" + }, + { + "name": "eslint-plugin-import", + "type": "build" + }, + { + "name": "eslint", + "version": "^8", + "type": "build" + }, + { + "name": "projen", + "type": "build" + }, + { + "name": "ts-node", + "type": "build" + }, + { + "name": "typescript", + "type": "build" + }, + { + "name": "nunjucks", + "type": "runtime" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." +} diff --git a/.projen/files.json b/.projen/files.json new file mode 100644 index 00000000..0c5c03b3 --- /dev/null +++ b/.projen/files.json @@ -0,0 +1,16 @@ +{ + "files": [ + ".eslintrc.json", + ".gitattributes", + ".gitignore", + ".npmignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "LICENSE", + "README.md", + "tsconfig.dev.json", + "tsconfig.json" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." +} diff --git a/.projen/tasks.json b/.projen/tasks.json new file mode 100644 index 00000000..0f78f8f7 --- /dev/null +++ b/.projen/tasks.json @@ -0,0 +1,247 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "default" + }, + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "bump": { + "name": "bump", + "description": "Bumps version based on latest git tag and generates a changelog entry", + "env": { + "OUTFILE": "package.json", + "CHANGELOG": "dist/changelog.md", + "BUMPFILE": "dist/version.txt", + "RELEASETAG": "dist/releasetag.txt", + "RELEASE_TAG_PREFIX": "", + "BUMP_PACKAGE": "commit-and-tag-version@^12" + }, + "steps": [ + { + "builtin": "release/bump-version" + } + ], + "condition": "git log --oneline -1 | grep -qv \"chore(release):\"" + }, + "clobber": { + "name": "clobber", + "description": "hard resets to HEAD of origin and cleans the local repo", + "env": { + "BRANCH": "$(git branch --show-current)" + }, + "steps": [ + { + "exec": "git checkout -b scratch", + "name": "save current HEAD in \"scratch\" branch" + }, + { + "exec": "git checkout $BRANCH" + }, + { + "exec": "git fetch origin", + "name": "fetch latest changes from origin" + }, + { + "exec": "git reset --hard origin/$BRANCH", + "name": "hard reset to origin commit" + }, + { + "exec": "git clean -fdx", + "name": "clean all untracked files" + }, + { + "say": "ready to rock! (unpushed commits are under the \"scratch\" branch)" + } + ], + "condition": "git diff --exit-code > /dev/null" + }, + "compile": { + "name": "compile", + "description": "Only compile", + "steps": [ + { + "exec": "tsc --build" + } + ] + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "ts-node --project tsconfig.dev.json .projenrc.ts" + } + ] + }, + "eject": { + "name": "eject", + "description": "Remove projen from the project", + "env": { + "PROJEN_EJECTING": "true" + }, + "steps": [ + { + "spawn": "default" + } + ] + }, + "eslint": { + "name": "eslint", + "description": "Runs eslint against the codebase", + "steps": [ + { + "exec": "eslint --ext .ts,.tsx --fix --no-error-on-unmatched-pattern $@ src test build-tools projenrc .projenrc.ts", + "receiveArgs": true + } + ] + }, + "install": { + "name": "install", + "description": "Install project dependencies and update lockfile (non-frozen)", + "steps": [ + { + "exec": "npm install" + } + ] + }, + "install:ci": { + "name": "install:ci", + "description": "Install project dependencies using frozen lockfile", + "steps": [ + { + "exec": "npm ci" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package", + "steps": [ + { + "exec": "mkdir -p dist/js" + }, + { + "exec": "npm pack --pack-destination dist/js" + } + ] + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "post-upgrade": { + "name": "post-upgrade", + "description": "Runs after upgrading dependencies" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "release": { + "name": "release", + "description": "Prepare a release from \"main\" branch", + "env": { + "RELEASE": "true" + }, + "steps": [ + { + "exec": "rm -fr dist" + }, + { + "spawn": "bump" + }, + { + "spawn": "build" + }, + { + "spawn": "unbump" + }, + { + "exec": "git diff --ignore-space-at-eol --exit-code" + } + ] + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "spawn": "eslint" + } + ] + }, + "unbump": { + "name": "unbump", + "description": "Restores version to 0.0.0", + "env": { + "OUTFILE": "package.json", + "CHANGELOG": "dist/changelog.md", + "BUMPFILE": "dist/version.txt", + "RELEASETAG": "dist/releasetag.txt", + "RELEASE_TAG_PREFIX": "", + "BUMP_PACKAGE": "commit-and-tag-version@^12" + }, + "steps": [ + { + "builtin": "release/reset-version" + } + ] + }, + "upgrade": { + "name": "upgrade", + "description": "upgrade dependencies", + "env": { + "CI": "0" + }, + "steps": [ + { + "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --dep=dev,peer,prod,optional --filter=@types/node,@types/nunjucks,eslint-import-resolver-typescript,eslint-plugin-import,projen,ts-node,typescript,nunjucks" + }, + { + "exec": "npm install" + }, + { + "exec": "npm update @types/node @types/nunjucks @typescript-eslint/eslint-plugin @typescript-eslint/parser commit-and-tag-version constructs eslint-import-resolver-typescript eslint-plugin-import eslint projen ts-node typescript nunjucks" + }, + { + "exec": "npx projen" + }, + { + "spawn": "post-upgrade" + } + ] + }, + "watch": { + "name": "watch", + "description": "Watch & compile in the background", + "steps": [ + { + "exec": "tsc --build -w" + } + ] + } + }, + "env": { + "PATH": "$(npx -c \"node --print process.env.PATH\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." +} diff --git a/.projenrc.ts b/.projenrc.ts new file mode 100644 index 00000000..37d27228 --- /dev/null +++ b/.projenrc.ts @@ -0,0 +1,1901 @@ +import { typescript } from 'projen'; +import { NodePackageManager } from 'projen/lib/javascript'; +import { READMEComponent } from './projenrc/projects/core-readme-component'; +import { DotNetQuickStartPOCs } from './projenrc/projects/dot-net-quickstart-pocs'; +import { POCReadmeDetails } from './projenrc/projects/resources/types'; +import { StreamlitQuickStartPOC } from './projenrc/projects/streamlit-quickstart-poc'; + +/** + * Base project for repo + */ +const project = new typescript.TypeScriptProject({ + authorName: 'AWS', + jest: false, + packageManager: NodePackageManager.NPM, + defaultReleaseBranch: 'main', + name: 'genai-quickstart-pocs', + projenrcTs: true, + github: false, + deps: ['nunjucks'], + devDeps: ['@types/nunjucks'], + gitignore: [ + '**/.DS_Store', + '**/__pycache__/', + '.env/', + 'venv', + 'output/', + 'genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/files/', + 'genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/generated-images/', + 'temp/', + 'cdk.out', + ], + tsconfig: { + compilerOptions: { + rootDir: '.', + sourceRoot: '.', + }, + include: [ + 'genai-quickstart-pocs-python/**/*', + 'projenrc/**/*', + ], + }, +}); + +const pythonPocs: Array = []; + +/** + * Python POCs + */ + +pythonPocs.push( + new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Alt Text Generator', + pocPackageName: 'amazon-bedrock-alt-text-generator', + additionalDeps: [ + 'langchain@^0.2', + 'langchain-community@^0.2', + 'langchain-aws', + 'pypdf', + 'pillow', + 'pymupdf', + 'reportlab', + ], + pocDescription: + 'This POC demonstrates how to use the Amazon Bedrock Alt Text Generator to generate alt text for images in PDF documents.', + readme: { + fileWalkthrough: { + includeDefaults: true, + files: [ + { + name: 'pdf_image_alt_text_generator/generator.py', + description: + 'The is the logic that extracts the data from PDF and calls the Bedrock Model for inference', + }, + { + name: 'pdf_image_alt_text_generator/download_results.py', + description: + 'generates a PDF with all images and their alt text results, as well as input/output token usage, calculated in a table.', + }, + ], + }, + }, + }), +); + +pythonPocs.push( + new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Amazon Athena POC', + pocPackageName: 'amazon-bedrock-amazon-athena-poc', + readme: { + additionalPrerequisits: [ + 'Access to Amazon Athena and the ability to create an Amazon Athena database and tables.', + ], + pocGoal: { + overview: + 'The goal of this POC is to provide users with the abilitity to use Amazon Bedrock and generative AI to take natural language questions and transform them into relational database querties against Amazon Athena.\n' + + 'The POC comes with a basic frontend to help users stand up a proof-of-concept in just a few minutes.', + architectureImage: true, + flowSteps: [ + 'The user makes a request, asking a natural language question based on the database available in Amazon Athena to the GenAI app (app.py).', + 'This natural language question is passed into Amazon Bedrock, which takes the natural language question and creates a SQL query (amazon_athena_bedrock_query.py).', + 'The created SQL query is then executed against your Amazon Athena database to begin retrieving the data (amazon_athena_bedrock_query.py).', + 'The data is retrieved from your Amazon Athena Database and is passed back into Amazon Bedrock, to generate a natural language answer based on the retrieved data (amazon_athena_bedrock_query.py).', + 'The LLM returns a natural language response to the user through the streamlit frontend based on the retrieved data (app.py).', + ], + }, + fileWalkthrough: { + files: [ + { + name: 'amazon_athena_bedrock_query.py', + description: + 'contains connectors into your Amazon Athena database and the interaction', + }, + { + name: 'moma_examples.yaml', + description: + 'contains several samples prompts that will be used to implement a few-shot prompting technique.', + }, + ], + }, + extraSteps: [ + { + instructions: + 'Create a .env file in the root folder of this POC. Within the .env file you just created you will need to configure the .env to contain:', + command: `profile_name= + \taws_access_key_id= + \taws_secret_access_key= + \tregion_name= + \tdatabase_name= + \ts3_staging_dir= example -> s3://sample-bucket/`, + }, + { + instructions: `If you would like to use this repo with the sample data, you will need to upload the two sample data files found in the sample data directory as two individual tables to your Amazon Athena Database. + +If you preferred to use your own database/tables in your Amazon Athena database, I would highly recommend reviewing the moma_examples.yaml file in the SampleData directory to see how prompts are constructed for this sample application and spend the time creating 5 - 10 prompts that resemble your dataset more closely.`, + }, + ], + }, + additionalDeps: [ + 'python-dotenv', + ], + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to use natural language questions to query relational data stores, specifically Amazon Athena. This example leverages the MOMA Open Source Database: https://github.com/MuseumofModernArt/collection.', + })); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock & Amazon RDS POC', + pocPackageName: 'amazon-bedrock-amazon-rds-poc', + additionalDeps: [ + 'langchain@^0.1', + 'langchain-community', + 'langchain-experimental', + ], + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to use natural language questions to query relational data stores, specifically Amazon RDS. This example leverages the MOMA Open Source Database: https://github.com/MuseumofModernArt/collection.', + readme: { + pocGoal: { + overview: + 'The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to take natural language questions, and transform them into relational database queries against Amazon RDS Databases. This repo is designed to work with\n' + + 'Amazon RDS Postgres, but can be configured to work with other database engine types.\n' + + 'This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.', + architectureImage: true, + flowSteps: [ + 'The user makes a request, asking a natural language question based on the data in Amazon RDS to the GenAI app (app.py).', + 'This natural language question is passed into Amazon Bedrock, which takes the natural language question and creates a SQL query (amazonRDS_bedrock_query.py).', + 'The created SQL query is then executed against your Amazon RDS database to begin retrieving the data (amazonRDS_bedrock_query.py).', + 'The data is retrieved from your Amazon RDS Database and is passed back into Amazon Bedrock, to generate a natural language answer based on the retrieved data (amazonRDS_bedrock_query.py).', + 'The LLM returns a natural language response to the user through the streamlit frontend based on the retrieved data (app.py).', + ], + }, + additionalPrerequisits: [ + 'Access to Amazon RDS and the ability to create an Amazon RDS database and tables.', + 'Please note that this project leverages the [langchain-experimental](https://pypi.org/project/langchain-experimental/) package which has known vulnerabilities.', + ], + fileWalkthrough: { + files: [ + { + name: 'amazonRDS_bedrock_query.py', + description: + 'contains connectors into your Amazon RDS database and the interaction', + }, + { + name: 'moma_examples.yaml', + description: + 'contains several samples prompts that will be used to implement a few-shot prompting technique.', + }, + ], + }, + extraSteps: [ + { + instructions: + 'Create a .env file in the root folder of this POC. Within the .env file you just created you will need to configure the .env to contain:', + command: + 'profile_name=' + + '\trds_username=' + + '\trds_password=' + + '\trds_endpoint=' + + '\trds_port=\n' + + '\trds_db_name=\n', + }, + { + instructions: `If you would like to use this repo with the sample data, you will need to upload the two sample data files found in the sample data directory as two individual tables to your Amazon RDS Postgres Database. + +If you preferred to use your own database/tables in your Amazon RDS instance, I would highly recommend reviewing the moma_examples.yaml file in the SampleData directory to see how prompts are constructed for this sample application and spend the time creating 5 - 10 prompts that resemble your dataset more closely.`, + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock & Amazon Redshift POC', + pocPackageName: 'amazon-bedrock-amazon-redshift-poc', + additionalDeps: [ + 'langchain@^0.1', + 'langchain-community', + 'langchain-experimental', + ], + pocDescription: + "This is sample code demonstrating the use of Amazon Bedrock and Generative AI to use natural language questions to query relational data stores, specifically Amazon Redshift. This example leverages the MOMA Open Source Database: https://github.com/MuseumofModernArt/collection.\n\n \t**Please Note: If you don't want to build this from scratch, Amazon Redshift now supports GenAI capabilities natively, more information on that can be found [here](https://aws.amazon.com/blogs/aws/amazon-redshift-adds-new-ai-capabilities-to-boost-efficiency-and-productivity/).**", + readme: { + pocGoal: { + architectureImage: true, + overview: + 'The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to take natural language questions, and transform them into relational database queries against Amazon Redshift Databases. This repo is designed to work with Amazon Redshift Provisioned Clusters. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.', + flowSteps: [ + 'The user makes a request, asking a natural language question based on the data in Amazon Redshift to the GenAI app (`app.py`)', + 'This natural language question is passed into Amazon Bedrock, which takes the natural language question and creates a SQL query (`amazon_redshift_bedrock_query.py`)', + 'The created SQL query is then executed against your Amazon Redshift cluster to begin retrieving the data (`amazon_redshift_bedrock_query.py`).', + 'The data is retrieved from your Amazon Redshift Database and is passed back into Amazon Bedrock, to generate a natural language answer based on the retrieved data (`amazon_redshift_bedrock_query.py`).', + 'The LLM returns a natural language response to the user through the streamlit frontend based on the retrieved data (`app.py`).', + ], + }, + additionalPrerequisits: [ + 'Access to Amazon Redshift and the ability to create an Amazon Redshift cluster and tables.', + 'Please note that this project leverages the [langchain-experimental](https://pypi.org/project/langchain-experimental/) package which has known vulnerabilities.', + ], + fileWalkthrough: { + files: [ + { + name: 'amazon_redshift_bedrock_query.py', + description: + 'contains connectors into your Amazon Redshift database and the interaction', + }, + { + name: 'moma_examples.yaml', + description: + 'contains several samples prompts that will be used to implement a few-shot prompting technique.', + }, + ], + }, + extraSteps: [ + { + instructions: + 'Create a .env file in the root folder of this POC. Within the .env file you just created you will need to configure the .env to contain:', + command: + 'profile_name=' + + '\tredshift_host= example -> redshift-cluster-1.abcdefghijk123.us-east-1.redshift.amazonaws.com' + + '\tredshift_username=' + + '\tredshift_password=' + + '\tredshift_endpoint=' + + '\tredshift_port=\n' + + '\tredshift_db_name=\n', + }, + { + instructions: + 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure lines 19-25 in the amazon_redshift_bedrock_query.py file:', + command: `llm = Bedrock( + credentials_profile_name=os.getenv("profile_name"), + model_id="amazon.titan-text-express-v1", + endpoint_url="https://bedrock-runtime.us-east-1.amazonaws.com", + region_name="us-east-1", + verbose=True +)`, + }, + { + instructions: `If you would like to use this repo with the sample data, you will need to upload the two sample data files found in the sample data directory as two individual tables to your Amazon Redshift Database. + +If you preferred to use your own database/tables in your Amazon Redshift instance, I would highly recommend reviewing the moma_examples.yaml file in the SampleData directory to see how prompts are constructed for this sample application and spend the time creating 5 - 10 prompts that resemble your dataset more closely.`, + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Asynchronous Invocation POC', + pocPackageName: 'amazon-bedrock-asynchronous-invocation-poc', + additionalDeps: [ + 'langchain@^0.1', + 'langchain-community', + 'langchain-experimental', + ], + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to perform asynchronous invocations of large language models. The application is constructed with a simple streamlit frontend where users can input zero shot requests directly against the LLM of their choice, leveraging asynchronous invocations, to invoke 3 models simultaneously to reduce overall latency.', + readme: { + pocGoal: { + overview: + 'The goal of this repo is to provide users the ability to use Amazon Bedrock and Generative AI to perform asynchronous invocations of large language models. The application is constructed with a simple streamlit frontend where users can input zero shot requests directly against the LLM of their choice, leveraging asynchronous invocations, to invoke 3 models simultaneously to reduce overall latency.', + architectureImage: true, + flowSteps: [ + 'The user makes a request, asking a natural language question based on the data in Amazon RDS to the GenAI app (app.py).', + 'This natural language question is passed into Amazon Bedrock, which takes the natural language question and creates a SQL query (amazonRDS_bedrock_query.py).', + 'The created SQL query is then executed against your Amazon RDS database to begin retrieving the data (amazonRDS_bedrock_query.py).', + 'The data is retrieved from your Amazon RDS Database and is passed back into Amazon Bedrock, to generate a natural language answer based on the retrieved data (amazonRDS_bedrock_query.py).', + 'The LLM returns a natural language response to the user through the streamlit frontend based on the retrieved data (app.py).', + ], + }, + fileWalkthrough: { + includeDefaults: false, + files: [ + { + name: 'app.py', + description: + 'contains the streamlit frontend and the interaction with Amazon Bedrock', + }, + { + name: 'amazon_bedrock_query.py', + description: + 'contains connectors into your Amazon Bedrock LLMs and the interaction', + }, + ], + }, + extraSteps: [ + { + instructions: + 'Create a .env file in the root folder of this POC. Within the .env file you just created you will need to configure the .env to contain:', + command: + 'profile_name=' + 'region_name=us-east-1', + }, + { + instructions: + 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 86 in the asynchronous_invocation.py file. Currently, this application is only suited to use Anthropic models:', + command: `async def orchestrator(question, modelID1="anthropic.claude-3-sonnet-20240229-v1:0", modelID2="anthropic.claude-3-haiku-20240307-v1:0", modelID3='anthropic.claude-v2:1'): + result = await asyncio.gather(main(question, modelID1), main(question, modelID2), main(question, modelID3)) + print(result) + return result`, + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Chat POC', + pocPackageName: 'amazon-bedrock-chat-poc', + additionalDeps: [ + 'langchain@^0.1', + 'langchain-community', + 'langchain-experimental', + ], + readme: { + pocGoal: { + architectureImage: true, + overview: + 'The goal of this repo is to provide users the ability to use Amazon Bedrock in a similar fashion to ChatGPT. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.', + flowSteps: [ + 'The user makes a "zero-shot" request to the streamlit frontend (`app.py`)', + 'The application returns the 3 most semantically similar prompts, and creates a final prompt that contains the 3 returned prompts along with users query (few-shot prompting) (`prompt_finder_and_invoke_llm.py`).', + 'The final prompt is passed into Amazon Bedrock to generate an answer to the users question (`prompt_finder_and_invoke_llm.py`).', + 'The final answer is generated by Amazon Bedrock and displayed on the frontend application (`app.py`)', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [ + { + name: 'prompt_finder_and_invoke_llm.py', + description: + 'houses the logic of the application, including the semantic search against the prompt repository and prompt formatting logic and the Amazon Bedrock API invocations.', + }, + { + name: 'chat_history_prompt_generator.py', + description: + 'houses the logic required to preserve session state and to dynamically inject the conversation history into prompts to allow for follow-up questions and conversation summary.', + }, + ], + }, + extraSteps: [ + { + instructions: + 'Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: 'profile_name=', + }, + { + instructions: + 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 23 in the prompt_finder_and_invoke_llm.py file to set the appropriate region:', + command: + "bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com')", + }, + { + instructions: + 'Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the llm_answer_generator() function in the prompt_finder_and_invoke_llm.py to look like:', + command: `def llm_answer_generator(question_with_prompt): + """ + This function is used to invoke Amazon Bedrock using the finalized prompt that was created by the prompt_finder(question) + function. + :param question_with_prompt: This is the finalized prompt that includes semantically similar prompts, chat history, + and the users question all in a proper multi-shot format. + :return: The final answer to the users question. + """ + # body of data with parameters that is passed into the bedrock invoke model request + # TODO: TUNE THESE PARAMETERS AS YOU SEE FIT + body = json.dumps({"prompt": question_with_prompt, + "max_tokens_to_sample": 8191, + "temperature": 0, + "top_k": 250, + "top_p": 0.5, + "stop_sequences": [] + }) + # configure model specifics such as specific model + modelId = 'anthropic.claude-v2' + accept = 'application/json' + contentType = 'application/json' + # Invoking the bedrock model with your specifications + response = bedrock.invoke_model(body=body, + modelId=modelId, + accept=accept, + contentType=contentType) + # the body of the response that was generated + response_body = json.loads(response.get('body').read()) + # retrieving the specific completion field, where you answer will be + answer = response_body.get('completion') + # returning the answer as a final result, which ultimately gets returned to the end user + return answer`, + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Claude 3 Image Analysis POC', + pocPackageName: 'amazon-bedrock-claude3-image-analysis-poc', + additionalDeps: [ + 'langchain@^0.1', + 'langchain-community', + 'langchain-experimental', + ], + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Multi-Modal Generative AI models from Anthropic to implement an image analysis use case. The application is constructed with a simple streamlit frontend where users can upload a 1 page jpeg, png or PDF and get a description of the image.', + readme: { + pocGoal: { + architectureImage: true, + overview: + 'The goal of this repo is to provide users with the ability to analyze images with Generative AI. This can be integrated into applications like image classification, reverse image lookup, object detection and more. This repo comes iwth a basic streamlit front-end to help users stand up a proof of concept and experiment with image analysis use-cases quickly.', + flowSteps: [ + 'The user uploads an image for bedrock model to analyze. (`app.py`).', + 'The streamlit app, takes the image input, and invokes Amazon Bedrock to generate a description (`analyze_images.py`).', + 'The image created by Amazon Bedrock is returned and displayed on the streamlit app (`app.py`).', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [ + { + name: 'analyze_images.py', + description: + 'house the logic of the application, including the semantic search against the prompt repository and prompt formatting logic and the Amazon Bedrock API invocations.', + }, + ], + }, + extraSteps: [ + { + instructions: + 'Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: 'profile_name=', + }, + { + instructions: + 'Depending on the region and model that you are planning to use with Amazon Bedrock (please note that only a few models can analyze images), you may need to reconfigure model paramaters in the image_analysis file. You might also choose to customize your prompts if this POC is for an industry-specific use-case analyzing a specific type of image:', + command: `brclient = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com',config=config) + +#model params +model_id = "anthropic.claude-3-sonnet-20240229-v1:0"`, + }, { + instructions: 'You may also choose to customize the system prompt to align with a pecific use-case, or to get specific responses back about your images. ', + command: 'system_prompt = "You are an expert in image analysis and classification. The question will be contained within the tags. Before answering, think step by step in tags as you analyze every part of the image. Provide your answer within the tags. Incude a JSON structured response describing image attributes contained within the tags. Always add line breaks between each section of your response"', + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Claude 3 Long Form Output POC', + pocPackageName: 'amazon-bedrock-claude3-long-form-output-poc', + additionalDeps: ['botocore', 'pypdf'], + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to translate text from a source to target language.', + readme: { + pocGoal: { + overview: 'The goal of this repository is to provide users with the ability to use Amazon Bedrock to generate long form content. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.', + architectureImage: true, + flowSteps: [ + 'The user either selects the default prompt or inputs a prompt.', + 'The application constructs the appropriate prompt and sends it to Amazon Bedrock.', + 'The appliction recieves and sends the text to Amazon Bedrock for analysis of accuracy and fluency.', + 'The generated text and analysis is displayed on the frontend application.', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [ + { + name: 'BedrockProcessor.py', + description: 'The logic for interacting with the Amazon Bedrock service.', + }, + ], + }, + extraSteps: [ + { instructions: 'Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', command: 'profile_name=' }, + { instructions: 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 23 in the prompt_finder_and_invoke_llm.py file to set the appropriate region:', command: 'bedrock = boto3.client(\'bedrock-runtime\', \'us-east-1\', endpoint_url=\'https://bedrock-runtime.us-east-1.amazonaws.com\')' }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Claude 3 Multi-Modal POC', + pocPackageName: 'amazon-bedrock-claude3-multi-modal-poc', + additionalDeps: ['pillow'], + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Anthropic Claude 3 to satisfy multi-modal use cases. The application is constructed with a simple streamlit frontend where users can input zero shot requests to satisfy a broad range of use cases, including image to text multi-modal style use cases.', + readme: { + pocGoal: { + overview: 'The goal of this repo is to provide users the ability to use Amazon Bedrock (specifically Claude3) and generative AI to leverage its multi-modal capabilities, allowing users to insert text questions, images, or both to get a comprehensive description/or answer based on the image and/or question that was passed in. \n This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.', + architectureImage: true, + flowSteps: [ + 'The user uploads an image file to the streamlit app, with or without a text question. (`app.py`)', + 'The user inserts a text question into to the streamlit app, with or without an image. (`app.py`)', + 'The streamlit app, takes the image file and/or text and saves it. The image and/or text is passed into Amazon Bedrock (Anthropic Claude 3). (`llm_multi_modal_invoke.py`)', + 'A natural language response is returned to the end user, either describing the image, answering a question about the image, or answering a question in general. (`app.py`)', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [ + { name: 'llm_multi_modal_invoke.py', description: 'Houses the logic of the application, including the image encoding and Amazon Bedrock API invocations' }, + ], + }, + extraSteps: [ + { + instructions: 'Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: `profile_name= +save_folder=`, + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Claude 3 Streaming Response POC', + pocPackageName: 'amazon-bedrock-claude3-streaming-response-poc', + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement streaming responses. The application is constructed with a simple streamlit frontend where users can input zero shot requests directly against the LLM of their choice, leveraging a streaming response technique.', +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Converse API POC', + pocPackageName: 'amazon-bedrock-converse-api-poc', + pocDescription: + 'This is sample code demonstrating the use of the Amazon Bedrock Converse API to help with conversation oriented use cases that require context preservation. The application is constructed with a simple streamlit frontend where users can input zero shot requests to Claude 3, with the Amazon Bedrock Converse API in place to allow users to ask context aware questions.', + readme: { + pocGoal: { + overview: 'The goal of this repo is to provide users the ability to use Amazon Bedrock leveraging its streaming response capabilities. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.', + architectureImage: true, + flowSteps: [ + 'The user inserts a text question into to the streamlit app. (`app.py`)', + 'The streamlit app, takes the text and passes it into Amazon Bedrock. (`invoke_llm_with_streaming.py`)', + 'A natural language response is streamed to the end user, answering a question in general. (`app.py`)', + ], + }, + fileWalkthrough: { + files: [ + { + name: 'invoke_llm_with_streaming.py', + description: 'Houses the invocation of Amazon Bedrock with a streaming response, and the basic prompt formatting logic.', + }, + ], + }, + extraSteps: [ + { + instructions: 'Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: 'profile_name=', + }, + { + instructions: 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 15 in the invoke_llm_with_streaming.py file to set the region or line 51 to change to another Claude 3 model such as Haiku:', + command: `bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') + +response = bedrock.invoke_model_with_response_stream(body=json_prompt, modelId="anthropic.claude-3-sonnet-20240229-v1:0", + accept="application/json", contentType="application/json")`, + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Converse Stream API POC', + pocPackageName: 'amazon-bedrock-converse-stream-api-poc', + pocDescription: + 'This is sample code demonstrating the use of the Amazon Bedrock ConverseStream API to help with conversation oriented use cases that require context preservation. The application is constructed with a simple streamlit frontend where users can input zero shot requests to Claude 3, with the Amazon Bedrock ConverseConverseStream API in place to allow users to ask context aware questions and stream the response back.', + readme: { + pocGoal: { + overview: 'The goal of this repo is to provide users the ability to use the Amazon Bedrock ConverseStream API to demonstrate its ability to facilitate conversational GenAI use cases that require context awareness and streaming responses. \n This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.', + architectureImage: true, + flowSteps: [ + 'The user inserts a text question into to the streamlit app. (`app.py`)', + 'The streamlit app, takes the text inserted by the user and is passed into an Amazon Bedrock Model using the Converse API. The users question is answered, and both the question and answer are stored. (`invoke_model_conversation_api.py`)', + 'The answer to the user\'s question is returned to the front-end application, and allows users to ask follow up questions as the Converse API help preserve context throughout the users conversation (`app.py`)', + ], + }, + additionalPrerequisits: [ + 'Create an Amazon Bedrock Guardrail, information on how to do that can be found [here](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-create.html)', + ], + fileWalkthrough: { + includeDefaults: true, + files: [ + { + name: 'invoke_model_converse_stream_api.py', + description: 'Houses the logic of the application, including the Amazon Bedrock Converse API invocation.', + }, + ], + }, + extraSteps: [ + { + instructions: 'create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: 'profile_name=', + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock CSV Chatbot POC', + pocPackageName: 'amazon-bedrock-csv-chatbot-poc', + additionalDeps: ['pandas'], + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a chatbot is able to converse with the user based on CSV data provided by the user. The application is constructed with a simple streamlit frontend where users can upload large CSV files and get them analyzed or start chatbot interactions.', + readme: { + pocGoal: { + overview: 'The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to answer questions a user might have on the CSV data provided. \n\nThis repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.', + architectureImage: true, + flowSteps: [ + 'The user uploads a CSV file to the streamlit app. (`app.py`)', + 'The streamlit app, takes the CSV file and chunks the document efficient data processing(`csv_data_insights.py`)', + 'Once the data is passed into Amazon Bedrock and the user asks the chatbot a question, it creates a response to the user\'s question (`csv_data_insights.py`).', + 'After the response is generated, it is presented on the streamlit app (`app.py`)', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [ + { + name: 'csv_data_insights.py', + description: 'Houses the logic of the application and Amazon Bedrock API invocations.', + }, + ], + }, + extraSteps: [ + { + instructions: 'reate a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain', + command: `profile_name= + save_folder=`, + }, + { + instructions: 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 10 in the `csv_data_insights.py` file to set your region:', + command: 'bedrock = boto3.client(\'bedrock-runtime\', \'us-east-1\', endpoint_url=\'https://bedrock.us-east-1.amazonaws.com\')', + }, + { + instructions: 'Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the line 143 in the `csv_data_insights.py` file to look like:', + command: 'response = bedrock.invoke_model(body=json_prompt, modelId="anthropic.claude-3-sonnet-20240229-v1:0", accept="application/json", contentType="application/json")', + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Document Comparison POC', + pocPackageName: 'amazon-bedrock-document-comparison-poc', + additionalDeps: [ + 'langchain@^0.1', + 'langchain-community', + 'langchain-experimental', + 'pypdf', + ], + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a document comparison use case. The application is constructed with a simple streamlit frontend where users can upload 2 versions of a document and get all changes between documents listed.', + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to perform document comparison between two uploaded PDFs. +This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.`, + architectureImage: true, + flowSteps: [ + 'The user uploads two PDF files to the streamlit app. (`app.py`)', + 'The streamlit app, takes the two PDF documents, saves it, and formats it into a prompt with semantically similar examples (`doc_comparer.py`)', + 'The finalized few shot prompt containing both uploaded documents is passed into Amazon Bedrock, which generates a list of all differences between the two uploaded documents and returns the final list to the front end (`doc_comparer.py`)', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [{ + name: 'doc_comparer.py', + description: 'Houses the logic of the application, including the prompt formatting logic and Amazon Bedrock API invocations.', + }], + }, + extraSteps: [ + { + instructions: 'reate a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: `profile_name= + save_folder=`, + }, + { + instructions: 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 20 in the doc_comparer.py file to set the appropriate region:', + command: 'bedrock = boto3.client(\'bedrock-runtime\', \'us-east-1\', endpoint_url=\'https://bedrock.us-east-1.amazonaws.com\')', + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Aamazon Bedrock Document Generator POC', + pocPackageName: 'amazon-bedrock-document-generator-poc', + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a document generation use case. The application is constructed with a simple streamlit frontend where users can provide details and create a document in the exact format that the you specify.', + readme: { + pocGoal: { + overview: 'The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to perform document generation based on a document template and details inputted by the user.\n\nThis repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.', + architectureImage: true, + flowSteps: [ + 'The user inserts document details that they would like included in the generated document within the streamlit app. (`app.py`)', + 'The streamlit app, takes the document details, and invokes Amazon Bedrock to generate sample document that matches the document structure stated in the prompt containing the inserted document details (`doc_generator.py`)', + 'Amazon Bedrock generates a first draft of the sample document and presents it to the frontend (`app.py`)', + 'The user inserts refinement details highlighting areas where they would like to add refinements to the previously generated document (`app.py`)', + 'The streamlit app takes the refinement details, passes it to Amazon Bedrock along with the document prompt, and the original draft of the document to begin creating the refined version (`doc_generator.py`)', + 'Amazon Bedrock is used to generate the refined version of the document based on the user defined refinements and presents it on the frontend (`app.py`)', + ], + }, + extraSteps: [ + { + instructions: 'create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: 'profile_name=', + }, + { + instructions: 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 12 in the document_generator.py file to set the appropriate region:', + command: 'bedrock = boto3.client(\'bedrock-runtime\', \'us-east-1\', endpoint_url=\'https://bedrock-runtime.us-east-1.amazonaws.com\')', + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock GenAI Dynamic Prompt Explained POC', + pocPackageName: 'amazon-bedrock-genai-dynamic-prompting-explained-poc', + additionalDeps: [ + 'langchain@^0.1', + 'langchain-community', + 'langchain-experimental', + ], + pocDescription: + 'This is sample code that can be used to provide a hands on explanation as to how Dynamic Prompting works in relation to Gen AI. The application is constructed with a simple streamlit frontend where users can ask questions against a Amazon Bedrock supported LLM and get a deeper understanding of how few-shot and dynamic prompting works.', + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock in a similar fashion to ChatGPT, in this case +the application has a strong focus on demonstrating on how prompts are dynamically selected based on the user inputted question. +This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.`, + architectureImage: true, + flowSteps: [ + 'The user makes a "zero-shot" request to the streamlit frontend. (app.py`)', + 'The application performs a semantic search of the users query against the 1200+ prompts. (`prompt_finder_and_invoke_llm.py`)', + 'The application returns the 3 most semantically similar prompts, and creates a final prompt that contains the 3 returned prompts along with users query (few-shot prompting) (`prompt_finder_and_invoke_llm.py`)', + 'The final prompt is passed into Amazon Bedrock to generate an answer to the users question (`prompt_finder_and_invoke_llm.py`)', + 'The final answer is generated by Amazon Bedrock and displayed on the frontend application along with 3 most semantically similar prompts (`app.py`)', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [ + { + name: 'prompt_finder_and_invoke_llm.py', + description: 'Houses the logic of the application, including the prompt formatting logic and Amazon Bedrock API invocations.', + }, + ], + }, + extraSteps: [ + { + instructions: 'create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: 'profile_name=', + }, + { + instructions: 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 12 in the prompt_finder_and_invoke_llm.py file to set the appropriate region:', + command: 'bedrock = boto3.client(\'bedrock-runtime\', \'us-east-1\', endpoint_url=\'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\')', + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Guardrails POC', + pocPackageName: 'amazon-bedrock-guardrails-poc', + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock Guardrails to help prevent prompt-injection attacks and prevent unintended responses from the LLM. The application is constructed with a simple streamlit frontend where users can input zero shot requests to Claude 3, with Amazon Bedrock Guardrails in place to prevent malicious prompts and responses.', + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock Guardrails to demonstrate its ability to prevent malicious prompts and responses. +This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.`, + architectureImage: true, + flowSteps: [ + 'The user inserts a text question into to the streamlit app. (`app.py`)', + 'The streamlit app, takes the text inserted by the user and is passed into an Amazon Bedrock Guardrail to check for prompt injection. If the prompt is detected as malicious or triggers the guardrail a response will be returned to the end user saying the request is blocked (`invoke_model_with_guardrails.py`)', + 'If the prompt does not trigger the guardrail it is passed into the bedrock model the user has specified (`invoke_model_with_guardrails.py`)', + 'A response is returned by the Amazon Bedrock Model of choice and is passed into the Amazon Bedrock Guardrail (`invoke_model_with_guardrails.py`). If the response is detected as malicious or triggers the guardrail a response will be returned to the end user saying the request is blocked (`invoke_model_with_guardrails.py`)', + 'If the response does not trigger a guardrail, a natural language response is returned to the end user answering the initial text question inserted by the end user (`app.py`)', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [ + { + name: 'invoke_model_with_guardrails.py', + description: 'Houses the logic of the application, including the prompt formatting logic and Amazon Bedrock API invocations.', + }, + ], + }, + extraSteps: [ + { + instructions: 'create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: `profile_name= + region_name= +guardrail_identifier= +guardrail_version= (this is just a number i.e. 1,2,3 etc...)`, + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Image Generation POC', + pocPackageName: 'amazon-bedrock-image-generation-poc', + additionalDeps: ['pillow'], + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement an image generation use case. The application is constructed with a simple streamlit frontend where users can input text requests to generate images based on the text input.', + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to create images based on text input requests. +This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.`, + architectureImage: true, + flowSteps: [ + 'The user inputs a text request asking to generate an image. (`app.py`)', + 'The streamlit app, takes the text input, and invokes Amazon Bedrock to generate an image (`image_generation.py`)', + 'The image created by Amazon Bedrock is returned and displayed on the streamlit app (`app.py`)', + ], + }, + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Knowledgebases RAG POC', + pocPackageName: 'amazon-bedrock-knowledgebases-rag-poc', + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to create vector embeddings for your data sources using Amazon Bedrock Knowledge bases with the ability ask questions against the stored documents. The application is constructed with a RAG based architecture where users can ask questions against the Knowledge bases.', +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock LangChain RAG POC', + pocPackageName: 'amazon-bedrock-langchain-rag-poc', + additionalDeps: [ + 'langchain@^0.1', + 'langchain-community', + 'langchain-experimental', + 'python-dotenv', + ], + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI using Langchain as orchestrator with the ability ask questions against the stored documents. This sample uses Knowledge bases as to retrieve the stored documents, however you can extend or update this sample to retrieve your stored documents from any Vector DB.', + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI using Langchain as orchestrator to create RAG based applications. +This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.`, + architectureImage: true, + flowSteps: [ + 'The user makes a request to the GenAI app (`app.py`)', + 'The app issues a get contexts query to the Amazon Bedrock Knowledge bases using Langchain based on the user request. (`query_with_langchain.py`)', + 'The knowledge bases returns search results related to the relevant documents from the ingested data. (`query_with_langchain.py`)', + 'The app sends the user request and along with the data retrieved from the Amazon Bedrock Knowlegebases as context in the LLM prompt to a LLM available within Bedrock using Langchain. (`query_with_langchain.py`)', + 'The LLM returns a succinct response to the user request based on the retrieved data. (`query_with_langchain.py`)', + 'The response from the LLM is sent back to the user. (`app.py`)', + ], + }, + extraSteps: [ + { + instructions: `Now that we have successfully cloned the repo, created and activated the virtual environment and installed the necessary dependencies, it is time for us to create Amazon Bedrock Knowledge base. + +To create our Amazon Bedrock Knowledge base we will: + +1. Go to the Amazon Bedrock Service homepage within the AWS console and on the left-hand side we will select "Knowledge bases" under the "Orchestration" drop down ![Alt text](images/amazon_bedrock_homepage.png "Amazon Bedrock Homepage") + +2. We will then click on "Create knowledge base" ![Alt text](images/knowledgeBase_homepage.png "Amazon Bedrock Create Knowledge base") + +3. In the Knowledge base details section, you can optionally change the default name and provide a description for your knowledge base.In the IAM permissions section, choose an AWS Identity and Access Management (IAM) role that provides Amazon Bedrock permission to access other AWS services. You can let Amazon Bedrock create the service role or choose a custom role that you have created. Optionally, add tags to your knowledge base. Select Next. ![Alt text](images/kb_first_page.png "Knowledge base details") + +4. On the Set up data source page, provide the information for the data source to use for the knowledge base: Optionally, change the default Data source name. Provide the S3 URI of the object containing the files for the data source that you prepared. Select Next. ![Alt text](images/kb_datasource_page.png "Set up Data Source") + +5. In the Embeddings model section, choose a supported embeddings model to convert your data into vector embeddings for the knowledge base. In the Vector database section, choose Quick create a new vector store and select Next ![Alt text](images/kb_vectordb_page.png "Select Embeddings Model") + +6. On the Review and create page, check the configuration and details of your knowledge base. Choose Edit in any section that you need to modify. When you are satisfied, select Create knowledge base.`, + }, + { + instructions: 'create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: `profile_name= +knowledge_base_id= +llm_model = < LLM model that you want to use for the POC, either "amazon-titan" or "anthropic-claude >`, + }, + { + instructions: 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 19 and 20 in the query_with_langchain.py file to change the region:', + command: `bedrock = boto3.client('bedrock-runtime', 'us-east-1') +bedrock_agent_runtime = boto3.client('bedrock-agent-runtime','us-east-1')`, + }, + { + instructions: `Since this repository is configured to leverage Amazon Titan or Anthropic Claude 3 models, the prompt payload is structured in formats required for the invocation of these two models. +If you wanted to leverage other Amazon Bedrock models, you can update \`query_with_langchain.py\` code. +For example if you to call Amazon Titan Lite instead of Amazon Titan Express, you can update call_titan funciton in \`query_with_langchain.py\` to look like the code below.\n +You can then change the model_id param value to the other available models from Amazon Titan. + +This repository is configured to leverage Knowledge bases. +If you want to use other Vector DBs that are not supported in Amazon Bedrock Knowledge Bases, or want to directly retreive contexts from Vector DB using langchain, you can refere to [this Langchain documentation](https://python.langchain.com/docs/modules/data_connection/retrievers/vectorstore/). +`, + command: `def call_titan(query, retriever): + """ + This function is used to call Amazon Titan Express LLM model using Langchain. + :param query: Contains the Question asked by the user + :param retriever: Contains the contexts retrieved from the Amazon Bedrock Knowledge base + :return: Response recieved from LLM for the input user query + """ + + # Setting Model kwargs + model_kwargs = { + "maxTokenCount": 4096, + "stopSequences": [], + "temperature": 0, + "topP": 1, + } + + # Setting LLM method from the Language Bedrock library + llm = Bedrock( + client=bedrock, model_id="amazon.titan-text-lite-v1", model_kwargs={} #updating the model_id param to to Amazon Titan Lite + ) + + # Invoke Amazon Titan using the Langchain llm method + qa = RetrievalQA.from_chain_type( + llm=llm, retriever=retriever, return_source_documents=True + ) + + answer = qa(query) + + # Returning the response + return answer `, + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Meeting Minutes Summarization POC', + pocPackageName: 'amazon-bedrock-meeting-minutes-summarization-poc', + additionalDeps: ['requests'], + pocDescription: + 'This application demonstrates using Amazon Bedrock and Amazon Transcribe to summarize meeting recordings. The streamlit frontend allows users to upload audio, video, or text files of meeting recording. Amazon Transcribe generates a transcript of recording and sent it Amazon Bedrock for summarization of the key discussion points. Users can then download the generated summarized meeting notes.', + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock and Amazon Transcribe to create Meeting minutes from audio ,video recordings. If audio +It show case the capablitiy to upload Audio, Video of meeting recording and create summary of meeting.`, + architectureImage: true, + flowSteps: [ + 'The user uploads a meeting recording video or audio or .txt file using Upload File button.', + 'Meeting recording is already present in Amazon Transcribe Job History Transcription text is retrieved from Job History', + 'If Meeting recording is not present in Amazon Transcribe Job history, recording file is temporary upload on S3 and Sent to Amazon Transcribe Job to generate transcription text ', + 'Transcription text is sent to Amazon Bedrock LLM for summarization', + 'Summarization notes are updated in streamlit app', + 'User can download the meeting notes', + ], + }, + additionalPrerequisits: [ + 'Access to Amazon Transcribe via your CLI Credentials', + 'Access to S3 Bucket with put,get,delete object permissions via your CLI credentials and accessible by Transcribe', + ], + extraSteps: [ + { + instructions: `Configure S3 Bucket required for temporary uploading the file + +Update the S3 Bucket name with your bucket name in **line 21** + +**app.py** :`, + command: 'S3_BUCKET_NAME = ""', + }, + ], + fileWalkthrough: { + includeDefaults: true, + files: [{ + name: 'llm.py', + description: 'This file has the logic to interact with LLM using Amazon Bedrock API. ', + }, { + name: 'transcribe_util.py', + description: 'This is the file that contains the logic to interact with Amazon Transcribe like starting Transcribe Job, getting Transcription job history, getting transcription text.', + }, { + name: 's3_util.py', + description: 'This is the file that contains the logic to interact with S3 bucket.', + }], + }, + }, +})); + + +// Not actually a streamlit poc, so manually defined README +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Model Customization', + pocPackageName: 'amazon-bedrock-model-customization', + pocDescription: 'This sample leverages Jupyter Notebooks to demonstrate how to customize bedrock models.', + excludeFromReadmeManagement: true, + readme: { + pocGoal: { + flowSteps: [], + overview: '', + architectureImage: false, + }, + }, + skipApp: true, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Model Evaluation Data Prep Tool', + pocPackageName: 'amazon-bedrock-model-eval-poc', + additionalDeps: ['bs4', 'pandas'], + pocDescription: + 'This is sample code aimed to accelerate customers aiming to leverage [Amazon Bedrock Model Evaluator](https://docs.aws.amazon.com/bedrock/latest/userguide/model-evaluation.html) with custom prompt data. This Proof-of-Concept (POC) enables users to provide a CSV containing data that should be used with Amazon Bedrock Model Evaluator. The user then maps the CSV columns to the appropriate fields depending on which type of Model Evaluation being executed. This will generate one or more `.jsonl` formatted files, ready for use with Amazon Bedrock Model Evaluator.', + readme: { + pocGoal: { + overview: 'The goal of this POC is to help customers understand how to transform data from CSV format to an Amazon Bedrock Model Evaluation dataset.', + architectureImage: false, + flowSteps: [ + 'Run the POC (see "How to use this Repo")', + 'Upload CSV of data to use with Model Evaluator', + 'Select the type of Model Evaluation being performed', + 'Map CSV columns to expected fields specific to the prompt type selected', + 'Download generated `.jsonl` file(s)', + 'Upload the generated `.jsonl` files to an Amazon S3 bucket that Amazon Bedrock Model Evalutor can access', + 'Execute Model Evaluation using custom prompts pointing to the newly uploaded prompt dataset. If you have more than 1,000 prompts, multiple files will have been generated. You can only execute model evaluation on a maximum of 1,000 records. ', + ], + }, + additionalPrerequisits: [ + 'Ensure you have access to an Amazon S3 bucket where you can upload generated data. Amazon Bedrock Model Evaluator will also need access to read and write to this bucket during Model Evaluation. ', + ], + fileWalkthrough: { + includeDefaults: true, + files: [{ + name: 'logic.py', + description: 'the logic that processes the data from the front-end', + }], + }, + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Model Playground POC', + pocPackageName: 'amazon-bedrock-model-playground-poc', + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a Gen AI model playground. The application is constructed with a simple streamlit frontend where users can input zero shot requests and select any LLM offered by Amazon Bedrock.', + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock and select any of the available Amazon Bedrock LLMs to ask zero shot requests. +This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.`, + architectureImage: true, + flowSteps: [ + 'The user selects the Amazon Bedrock Model they want to use and makes a "zero-shot" request to the streamlit frontend. (`app.py`).', + 'The application takes the question and the model chosen and routes it to the appropriate model (`model_invoker.py`). All specific model invocations are stored in (model_selector.py).', + 'The final answer is generated by the Amazon Bedrock Model chosen and displayed on the frontend application (`app.py`).', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [{ + name: 'model_invoker.py', + description: 'This file has the logic to interact with LLM using Amazon Bedrock API. ', + }, { + name: 'model_selector.py', + description: 'This is the file that contains the logic to map the model selected by the user to the appropriate Amazon Bedrock Model.', + }], + }, + extraSteps: [ + { + instructions: 'reate a .env file in the root of this POC specific directory within this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: `profile_name= +region_name=us-east-1 (region of choice)`, + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock RAG with Kendra POC', + pocPackageName: 'amazon-bedrock-rag-kendra-poc', + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a RAG based architecture with Amazon Kendra. The application is constructed with a simple streamlit frontend where users can ask questions against documents stored in Amazon Kendra.', + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to take natural language questions, and answer questions against indexed documents in Amazon Kendra. +This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.`, + architectureImage: true, + flowSteps: [ + 'The user makes a request to the GenAI app (`app.py`).', + 'The app issues a search query to the Amazon Kendra index based on the user request. (`kendra_bedrock_query.py`)', + 'The index returns search results with excerpts of relevant documents from the ingested data. (`kendra_bedrock_query.py`)', + 'The app sends the user request and along with the data retrieved from the index as context in the LLM prompt. (`kendra_bedrock_query.py`)', + 'The LLM returns a succinct response to the user request based on the retrieved data. (`kendra_bedrock_query.py`)', + 'The response from the LLM is sent back to the user. (app.py)', + ], + }, + additionalPrerequisits: [ + 'Access to create and configure Amazon Kendra Indexes', + ], + fileWalkthrough: { + includeDefaults: true, + files: [{ + name: 'kendra_bedrock_query', + description: 'The logic of the application, including the Kendra Retrieve API calls and Amazon Bedrock API invocations.', + }], + }, + extraSteps: [ + { + instructions: `**Create your Amazon Kendra Index (if you don't already have one)** + \t\t1. Go to Amazon Kendra in your AWS Console and click on "Create an Index" ![Alt text](images/Amazon_kendra_homepage.png "Kendra Homepage") + \t\t2. Fill out the "Specify Index details" page, and provide Kendra a role that can access CloudWatch Logs. ![Alt text](images/kendra_specify_index_details.png "Kendra Specify Details Page") + \t\t3. Fill out the "Configure Access Control" page ![Alt text](images/kendra_access_control.png "Kendra Access Control") + \t\t4. Select the appropriate provisioning editions and create ![Alt text](images/specify_provisioning_kendra.png "Kendra Edition Selection") + \t\t5. You can find your Kendra Index ID in the console as seen in the screenshot: ![Alt text](images/kendra_screen_shot.png "Kendra Index")`, + }, + { + instructions: 'Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: `profile_name= +kendra_index=`, + }, + { + instructions: 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 11 in the kendra_bedrock_query.py file to change the region:', + command: 'bedrock = boto3.client(\'bedrock-runtime\', \'us-east-1\', endpoint_url=\'https://bedrock.us-east-1.amazonaws.com\')', + }, + { + instructions: `Time to sync a data source within Kendra. As seen in the screenshot below, you can configure the specific datasource that you would like to sync. For more information +on data sources feel free to refer to this [documentation](https://docs.aws.amazon.com/kendra/latest/dg/hiw-data-source.html). + +![Alt text](images/kendra_data_source.png "Kendra Data Source") + +**_If you don't have your own sample data, or sample data source you can leverage the sample datasource within Amazon Kendra data sources as shown below:_** + + \t\t1. On the data sources tab, click on the add dataset option as seen in the image: ![Alt text](images/sample_data_sources.png "Kendra Sample Data Source") + \t\t2. Then define the data sources attributes such as the data source name and click add data source: ![Alt text](images/sample_data_source_configuration.png "Kendra Sample Data Source Config") + \t\t3. This will automatically create the data source and triggers a sync. You will now be able to ask questions against Sample AWS Documentation that covers Kendra, EC2, S3 and Lambda in your front end application. +`, + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock RAG with OpenSearch Serverless POC', + pocPackageName: 'amazon-bedrock-rag-opensearch-serverless-poc', + additionalDeps: [ + 'opensearch-py', + 'langchain@^0.1', + 'langchain-community', + 'langchain-experimental', + ], + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to create custom embeddings stored in Amazon OpenSearch Serverless with the ability ask questions against the stored documents. The application is constructed with a RAG based architecture where users can ask questions against the indexed embeddings within OpenSearch Serverless.', + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to take natural language questions, and answer questions against embedded and indexed documents in Amazon OpenSearch Serverless Vector Search. +This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.`, + architectureImage: true, + flowSteps: [ + 'The user makes a request to the GenAI app (`app.py`)', + 'The app issues a k-nearest-neighbors search query to the Amazon OpenSearch Serverless Vector Search index based on the user request. (`query_against_opensearch.py`)', + 'The index returns search results with excerpts of relevant documents from the ingested data. (`query_against_opensearch.py`)', + 'The app sends the user request and along with the data retrieved from the Amazon OpenSearch Serverless Vector Search index as context in the LLM prompt. (`query_against_opensearch.py`)', + 'The LLM returns a succinct response to the user request based on the retrieved data. (`query_against_opensearch.py`)', + 'The response from the LLM is sent back to the user. (`app.py`)', + ], + }, + additionalPrerequisits: [ + 'Access to create and configure Amazon OpenSearch Serverless collections', + ], + fileWalkthrough: { + includeDefaults: true, + files: [{ + name: 'docs_to_openSearch.py', + description: 'the logic needed to take a PDF document stored on your local machine, creating the embeddings and storing it in your OpenSearch Index.', + }, { + name: 'query_against_opensearch.py', + description: 'The logic of the application, including the Amazon OpenSearch Serverless Vector Search calls and Amazon Bedrock API invocations.', + }], + }, + extraSteps: [ + { + instructions: `Create the Amazon OpenSearch Serverless Vector Search collection. + + To create our Amazon OpenSearch Vector Search Collection we will: + + 1. Go to the Amazon OpenSearch Service homepage within the AWS console and on the left-hand side we will select "Collections" under the "Serverless" drop down ![Alt text](images/Amazon_OpenSearch_Homepage.png "Amazon OpenSearch Serverless Homepage") + 2. We will then click on "Create collection" ![Alt text](images/create_collection.png "Amazon OpenSearch Create Collection") + 3. On the "Configure collection settings" page, we will need to input a "Collection name", select the "Collection type": "Vector search", in the "Security" section select the option "Standard create", and select your preferred "Encryption" settings: ![Alt text](images/Configure_collection_settings_part_1.png "Amazon OpenSearch Serverless Collection Settings Part-1") + 4. On the same "Configure collection settings" page, at the bottom we will select our "Network access settings" either "Public" or "VPC", and give access to the OpenSearch Endpoint and/or OpenSearch Dashboards and select next ![Alt text](images/configure_collection_settings_part_2.png "Amazon OpenSearch Create Collection Part 2") + 5. On the "Configure data access" page we must input a "Rule name", add the user for which you have CLI credentials for, and for the sake of the POC Grant all permissions and select Next ![Alt text](images/configure_data_access.png "Amazon OpenSearch Configure Data Access") + 6. We will then enter an access policy name and select Next ![Alt text](images/access_policy_definition.png "Amazon OpenSearch Configure Data Access Part 2") + 7. We will confirm all of our configuration items, and press Submit ![Alt text](images/collection_create_confirm.png "Amazon OpenSearch Collection Confirm") + 8. As soon as the collection is created, you will want to **BE SURE TO NOTE DOWN THE OPENSEARCH ENDPOINT** ![Alt text](images/OpenSearch-endpoint.png "Amazon OpenSearch Endpoint")`, + }, { + instructions: `With our Amazon OpenSearch Serverless Vector Search collection created, we now must create our Vector Index. As soon as this is created we will begin indexing our PDF document. + + 1. Within the OpenSearch Serverless Collection we just created, we will select "Create vector index" ![Alt text](images/create_vector_index.png "Create Vector Index") + 2. We will then input a Vector Index Name, Vector Field Name, Dimensions and distance metric... **BE SURE TO NOTE DOWN THE VECTOR INDEX NAME AND VECTOR FIELD NAME**. The Dimensions field is expecting an integer, in our case since we are using the 'amazon.titan-embed-text-v1' embeddings model, the dimension size will be 1536. If you plan on using a different embeddings model you will need to change this value to represent the output vector size of that specific model. Then Select "Create" ![Alt text](images/create_vector_index_name.png "Create Vector Index Details") ![Alt text](images/vector_field.png "Create Vector Index Details") + 3. **_OPTIONAL:_** If you want to add meta-data to your documents that you plan on indexing, you must specify those fields in this vector index configuration. If you plan on adding meta-data you will need to reconfigure some of the code in the docs_to_openSearch.py file ![Alt text](images/metadata.png "Add Meta-Data")`, + }, { + instructions: 'create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: `profile_name= +opensearch_host= example->abcdefghijklmnop1234.us-east-1.aoss.amazonaws.com +vector_index_name= +vector_field_name=`, + }, { + instructions: 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 12 in the query_against_openSearch.py file to change the region:', + command: 'bedrock = boto3.client(\'bedrock-runtime\', \'us-east-1\', endpoint_url=\'https://bedrock.us-east-1.amazonaws.com\')', + }, { + instructions: `After you create your .env file, it is time to create the embeddings for a sample PDF document of your choosing. +All you will need to do, is specify the path to that PDF document in line 42 of the docs_to_openSearch.py file. +Optionally you can also try different values for the document chunk size in line 47 - line 51 of the same docs_to_openSearch.py file. +As soon as you are satisfied with the configuration, you can simply run the file while in the root of the repo with the command below. \n +**_Depending on the size of your document this process can range from seconds to hours_**\n`, + command: 'python3 docs_to_openSearch.py', + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Semantic Cache POC', + pocPackageName: 'amazon-bedrock-semantic-cache-poc-main', + additionalDeps: ['opensearch-py'], + pocDescription: + 'This project demonstrates a Retrieval-Augmented Generation (RAG) system using Amazon Bedrock for knowledge retrieval and OpenSearch for semantic caching. It provides a Streamlit-based user interface for asking questions about data stored in Amazon Knowledge Bases.', + readme: { + pocGoal: { + overview: `The primary goal of this repository is to showcase an efficient and scalable question-answering system that combines the power of Large Language Models (LLMs) with a knowledge base and semantic caching. + The approach aims to: + 1. Provide fast and accurate answers to user queries + 2. Reduce the load on the LLM and knowledge base by utilizing a semantic cache + 3. Reduce the cost of the system by limiting calls to the LLM + 4. Demonstrate the integration of Amazon Bedrock and OpenSearch for semantic caching purposes`, + architectureImage: true, + flowSteps: [ + 'Load documents and crawl websites to add data into knowledge base', + 'User submits a question through the Streamlit UI', + 'The system checks the semantic cache (OpenSearch) for similar previous queries', + 'If a cache hit occurs, the stored answer is returned immediately', + 'If no cache hit, the system queries the Amazon Bedrock Knowledge Base for relevant context', + 'The retrieved context and user question are sent to an LLM (Claude 3) for answer generation', + 'The new question-answer pair is stored in the semantic cache', + 'The answer is displayed to the user in the Streamlit interface', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [{ + name: 'knowledge_base.py', + description: 'Functions for interacting with Amazon Bedrock Knowledge Base', + }, { + name: 'semantic_cache.py', + description: 'Functions for semantic caching using OpenSearch', + }, { + name: 'utils.py', + description: 'Utility functions and shared configurations', + }], + }, + additionalPrerequisits: [ + 'A Amazon Bedrock Knowledge Base with Amazon OpenSearch as the Vector Store. Instructions can be found [here](https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base-create.html).', + ], + extraSteps: [ + { + instructions: 'Create a `.env` file in the project root with the following variables:', + command: `PROFILE_NAME=your_aws_profile_name +AWS_REGION=your_aws_region +OPENSEARCH_HOST=your_opensearch_host +OPENSEARCH_INDEX=your_opensearch_index (Note: Specify a name like semantic-cache-index. This will be a seperate index than your knowledge base which will be created by the application) +KNOWLEDGE_BASE_ID=your_knowledge_base_id`, + }, + { + instructions: `Update OpenSearch permissions to allow access from the CLI and to grant delete actions + + a. Navigate to OpenSearch Serverless Collections + + ![Alt text](image/os-permissions-1.png) + + b. Select your Collection + + ![Alt text](image/os-permissions-2.png) + + c. Click on Data Access Control + + ![Alt text](image/os-permissions-3.png) + + d. Select Edit + + ![Alt text](image/os-permissions-4.png) + + e. Add your CLI user as a principal + + ![Alt text](image/os-permissions-5.png) + + f. Grant Delete Collection Items on the collection and Delete Index on the index and click Save + + ![Alt text](image/os-permissions-6.png)`, + }, + ], + finalText: `## Considerations + +Other vector db's can be used to implement semantic caching. Here a a few helpful links to explore: + +1. [Semantic Caching with MemoryDB](https://aws.amazon.com/blogs/database/improve-speed-and-reduce-cost-for-generative-ai-workloads-with-a-persistent-semantic-cache-in-amazon-memorydb/) +2. [Semantic Caching with LangChain](https://python.langchain.com/v0.2/docs/integrations/llm_caching/) + +Please note that only specific models can be used with Amazon Bedrock Knowledge Bases and with the Amazon Bedrock Converse API. +1. Amazon Bedrock Converse API - Supported [models](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html) and model features +2. Amazon Bedrock Knowledge Bases - Supported [models](https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base-supported.html) by action`, + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Speech to Text POC', + pocPackageName: 'amazon-bedrock-speech-to-text-chat-poc', + additionalDeps: [ + 'sounddevice', + 'amazon-transcribe', + 'langchain@^0.1', + 'langchain-community', + 'langchain-experimental', + ], + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a ChatGPT alternative using speech-to-text prompts. The application is constructed with a simple streamlit frontend where users can provide zero shot requests using their computer’s microphone and listen to responses to satisfy a broad range of use cases.', + readme: { + pocGoal: { + overview: 'The goal of this repo is to provide users the ability to use Amazon Bedrock in a similar fashion to ChatGPT by invoking the model using their speech rather than typing. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.', + architectureImage: true, + flowSteps: [ + 'The user makes a "zero-shot" request to the streamlit frontend (app.py) by speaking into their computer’s microphone.', + 'The live audio is streamed to Amazon Transcribe (live_transcription.py)', + 'The transcribed text is streamed back to the streamlit frontend (app.py) once the user has finished speaking.', + 'The application performs a semantic search of the users query against the 1200+ prompts. (prompt_finder_and_invoke_llm.py).', + 'The application returns the 3 most semantically similar prompts, and creates a final prompt that contains the 3 returned prompts along with users query (few-shot prompting) (prompt_finder_and_invoke_llm.py).', + 'The final prompt is passed into Amazon Bedrock to generate an answer to the user’s question (prompt_finder_and_invoke_llm.py).', + 'The final answer is generated by Amazon Bedrock and displayed on the frontend application (app.py).', + 'The final answer is passed to Amazon Polly to convert the text to natural sounding speech (app.py)', + 'The audio file is returned and played through the frontend application (app.py)', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [{ + name: 'chat_history_prompt_generator.py', + description: 'logic required to preserve session state and to dynamically inject the conversation history into prompts to allow for follow-up questions and conversation summary.', + }, { + name: 'live_transcription.py', + description: 'logic required to create an audio stream from the users microphone, send the audio chunks to Amazon Transcribe, and generate a text transcript. The requirements.txt file contains all necessary dependencies for this sample application to work.', + }, { + name: 'prompt_finder_and_invoke_llm.py', + description: 'logic of the application, including the semantic search against the prompt repository and prompt formatting logic and the Amazon Bedrock API invocations.', + }], + }, + extraSteps: [ + { + instructions: ' create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: 'profile_name=', + }, { + instructions: 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 23 in the prompt_finder_and_invoke_llm.py file to set the appropriate region:', + command: 'bedrock = boto3.client(\'bedrock-runtime\', \'us-east-1\', endpoint_url=\'https://bedrock-runtime.us-east-1.amazonaws.com\')', + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Streaming Response POC', + pocPackageName: 'amazon-bedrock-streaming-response-poc', + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement streaming responses. The application is constructed with a simple streamlit frontend where users can input zero shot requests directly against the LLM of their choice, leveraging a streaming response technique.', + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock leveraging its streaming response capabilities. +This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.`, + architectureImage: true, + flowSteps: [ + 'The user inserts a text question into to the streamlit app. (app.py).', + 'The streamlit app, takes the text and passes it into Amazon Bedrock. (invoke_llm_with_streaming.py).', + 'A natural language response is streamed to the end user, answering a question in general. (app.py).', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [{ + name: 'invoke_llm_with_streaming.py', + description: 'The logic required to invoke Amazon Bedrock and stream the response back to the frontend application (app.py).', + }], + }, + extraSteps: [ + { + instructions: ' create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: 'profile_name=', + }, { + instructions: 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 15 & 39 in the invoke_llm_with_streaming.py file:', + command: `bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') + + modelId = 'anthropic.claude-v2'`, + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Summarization of Long Documents POC', + pocPackageName: 'amazon-bedrock-summarization-long-document-poc', + additionalDeps: [ + 'langchain@^0.1', + 'langchain-community', + 'langchain-experimental', + 'pypdf', + ], + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a long document summarization use case. The application is constructed with a simple streamlit frontend where users can upload large documents and get them summarized.', + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to create summaries of large PDF files with chunking logic. +This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.`, + architectureImage: true, + flowSteps: [ + 'The user uploads a PDF file to the streamlit app. (app.py).', + 'The streamlit app, takes the PDF document, saves it, and chunks the document (doc_summarizer.py).', + 'Each chunk of the document is passed into Amazon Bedrock, which summarizes each chunk, and then performs a summarization of all chunks (doc_summarizer.py).', + 'After the final summarization is completed, the final summary is presented on the streamlit app (app.py).', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [{ + name: 'doc_summarizer.py', + description: 'The logic required to chunk the document, invoke Amazon Bedrock, and perform the final summarization (doc_summarizer.py).', + }], + }, + extraSteps: [ + { + instructions: 'Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: `profile_name= +save_folder=`, + }, + { + instructions: 'Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure in the doc_summarizer.py file:', + command: 'bedrock = boto3.client(\'bedrock-runtime\', \'us-east-1\', endpoint_url=\'https://bedrock.us-east-1.amazonaws.com\'', + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Task Classification POC', + pocPackageName: 'amazon-bedrock-task-classification', + pocDescription: + 'This sample code demonstrates how to use Amazon Bedrock and Generative AI to implement a task classification bot. The application is constructed with a simple streamlit frontend where users can input a task and get the correct classification which then trigger appropriate downstream workflows to process the task inputted. ', + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to classify a task, and thus the ability to auto trigger downstream workflows that are designed to process these tasks. +This repo comes with a basic front end to help users stand up a proof of concept in just a few minutes.`, + architectureImage: true, + flowSteps: [ + 'The user input task with relevant details into the streamlit app (app.py).', + 'The streamlit app, takes the task with description and pass it along to a helper file (task_classification.py).', + 'This helper file calls the Bedrock API and wraps the user prompt with a system prompt, parsing user\'s input and add further requirements.', + `Amazon Bedrock responses to the user's task in 2 items. + * What class the task belongs to + * Model's further processing of task details (to then be pass on to appropriate downstream processes)`, + 'The application parse the two items from the model outputs to perform next steps (task_classification.py).', + 'A visual confirmation on streamlit app (pop up modal) to ensure the correct class is assigned to the task inputted (app.py). ', + ], + }, + fileWalkthrough: { + includeDefaults: true, + files: [{ + name: 'task_classification.py', + description: 'The logic required to invoke Amazon Bedrock and parse the response', + }], + }, + extraSteps: [ + { + instructions: 'Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: 'profile_name=', + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Translation POC', + pocPackageName: 'amazon-bedrock-translation-poc', + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to translate text from a source to target language.', + readme: { + pocGoal: { + overview: 'The goal of this repository is to provide users with the ability to use Amazon Bedrock to perform translations. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.', + architectureImage: true, + flowSteps: [ + `Text: + 1. The user inputs text and selects the source and target language. + 2. The application constructs the appropriate prompt for translation and sends it to Amazon Bedrock. + 3. The appliction recieves and sends the translated text to Amazon Bedrock for analysis of accuracy and fluency. + 4. The translated text and analysis is displayed on the frontend application.`, + `Chat: + 1. The user inputs text and selects the target language. + 2. The application constructs the appropriate prompt for translation and sends it to Amazon Bedrock. + 3. The translated response is displayed on the frontend application.`, + `File: + 1. The user uploads a text file and selects the target language. + 2. The application constructs the appropriate prompt for translation and sends it to Amazon Bedrock. + 3. The translated text from the document is displayed on the frontend application.`, + ], + }, + fileWalkthrough: { + includeDefaults: false, + files: [{ + name: 'Text.py', + description: 'Frontend for Text Translate', + }, { + name: 'Chat.py', + description: 'Frontend for Chat Translate', + }, { + name: 'File.py', + description: 'Frontend for File Translate', + }, { + name: 'amazon_bedrock_translation.py', + description: 'Logic required to invoke Amazon Bedrock and parse the response', + }, { + name: 'requirements.txt', + description: 'Python dependencies', + }], + }, + extraSteps: [ + { + instructions: 'Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: 'profile_name=', + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Video Chapter Creator POC', + pocPackageName: 'amazon-bedrock-video-chapter-creator-poc', + additionalDeps: ['langchain@^0.1', 'pandas', 'opensearch-py', 'thefuzz'], + pocDescription: + `This is sample code demonstrating the use of Amazon Transcribe, Amazon OpenSearch Serverless, Amazon Bedrock and Generative AI, to a implement video chapter generator and video search sample. + The application is constructed with a simple streamlit frontend where users can upload a video that will be stored, transcribed and have searchable chapters generated. Additionally, if you have videos already uploaded to S3 and have subtitles for the video already created in \`.srt\` format, you can skip transcribing and jump straight into generating chapters.\n\n + The sample also includes a second UI that allows the user to ask about a topic. This will search the video chapters from the videos you've provided and provide a video, set to a specific chapter, that was the closest match to the inquiry.`, + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to create video chapters and searching those chapters. + \tThis repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. + \tThe application is constructed with a simple streamlit frontend where users can upload a video that will be stored, transcribed and have searchable chapters generated. Additionally, if you have videos already uploaded to S3 and have subtitles for the video already created in \`.srt\` format, you can skip transcribing and jump straight into generating chapters. + \t\tThe sample also includes a second UI that allows the user to ask about a topic. This will search the video chapters from the videos you've provided and provide a video, set to a specific chapter, that was the closest match to the inquiry. +`, + architectureImage: true, + flowSteps: [ + ` 1. The user uploads a video file or provides an uploaded file s3 oject to the streamlit app. + 2. The streamlit app, takes the video, transcribes it and uses the transcription to determine spots that make sense as chapters. + 3. Each chapter is then sent to the LLM to locate a good spot to start the chapter that gives some context as to the content amd doesn't drop the user into the middle of the content. + 4. The chapters are then returned to the user, who can then save the chapters to the OpenSearch Collection. `, + + `On the search side: + 1. The user asks an inquiry via the streamlit app. + 2. The query is passed the the LLM with the OpenSearch collection as a source. + 3. The OpenSearch collection provides the chapter, which is then returned with the video to set the user to the correct spot in the video. `, + ], + }, + additionalPrerequisits: [ + `An OpenSearch Serverless Collection. You can learn how to create one [here](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/serverless-vector-search.html). +*The Easy Create instructions on the document are suitable for this* +Within the Collection, a Vector Index is needed, with a Vector Field called \`vectors\` with an Engine value of \`mmslib\`, Dimensions of \`1536\`. The remaining options can be left with their default values.`, + 'An Amazon S3-Backed CloudFront Distribution. Videos will be uploaded to this S3 bucket and users will access videos through the CloudFront distribution. You can learn how to deploy the CloudFront an S3 bucket configuration [here](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/GettingStarted.SimpleDistribution.html). ', + ], + fileWalkthrough: { + includeDefaults: true, + files: [{ + name: 'videochapterlogic.py', + description: 'This is the logic that the UI connects to. The functions perform the logic and API calls to the AWS service endpoints like Amazon Transcribe, Amazon Bedrock, etc. `app.py` imports `videochapterlogic` functions.', + }, { + name: 'environment.toml', + description: 'This is the file that contains the configurations specific to your AWS environment like the S3 Bucket or OpenSearch Collection endpoint. The values in this file are required in order for the application to function.', + }, { + name: '.streamlit/config.toml', + description: 'The streamlit configuration file with paremters set to override the default configuration. Generally you won\'t need to adjust this unless you want to further customize the streamlit app. ', + }], + }, + extraSteps: [ + { + instructions: `Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. + +Open the \`environment.toml\` file and fill in the properties with your resources`, + }, + ], + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock PowerPoint Generator', + pocPackageName: 'amazon-bedrock-powerpoint-generator-poc', + additionalDeps: [ + 'langchain@^0.3', + 'langchain-aws', + 'langchain-community', + 'python-pptx', + 'uuid', + 'wikipedia', + 'pypdf', + 'docx2txt', + ], + pocDescription: + 'This is sample code demonstrates the use of Amazon Bedrock and Generative AI to implement a PowerPoint generator. The application is constructed with a simple streamlit frontend where users can input a topic and get a PowerPoint generated based on the topic. Using Generative AI, the solution creates relevant Wikipedia queries to perform in-depth research on the presentation content.', + readme: { + pocGoal: { + architectureImage: false, + overview: + 'The goal of this POC is to showcase leveraging Generative AI for to create both the content for a presentation and also the background research queries to support the content generation.', + }, + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Intelligent Document Processing (IDP) POC', + pocPackageName: 'amazon-bedrock-intelligent-document-processing-poc', + pocDescription: + 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI incorporated into an Intelligent Document Processing (IDP) pipeline using user-uploaded documents. The application is constructed with a simple streamlit frontend where users can upload various document formats and perform different IDP actions such as text extraction, document summarization and classification, entity recognition, and Q&A to satisfy a broad range of use cases.', + readme: { + pocGoal: { + architectureImage: true, + overview: + 'The goal of this repo is to provide users the ability to use various Amazon AI services utilized in an IDP pipeline combined with Amazon Bedrock to improve performance, complete tasks faster, and limit human review. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.', + flowSteps: [ + 'The user selects and uploads a document to the streamlit frontend (upload_doc_to_s3.py).', + 'The document is uploaded to an Amazon S3 bucket (upload_doc_to_s3.py, s3_utils.py)', + 'The raw text and key-value pairs are extracted from the document using Amazon Textract (extract_text_with_textract.py, textract_utils.py)', + 'The extracted key-value pairs are grammatically corrected using Amazon Bedrock, where the enriched output is saved to the local directory (enrich_doc_with_bedrock.py, bedrock_utils.py)', + 'The enriched output is then analyzed by Amazon Comprehend to detect entities such as people, organizations, locations, and more (entity_recognition_with_comprehend.py, comprehend_utils.py).', + 'The enriched output is then passed to Amazon Bedrock for document classification, summarization, and Q&A tasks. Bedrock’s multimodal capabilities can also be compared at each these stages by analyzing the document as is (classify_doc_with_bedrock.py, summarize_doc_with_bedrock.py, doc_qa_with_bedrock.py, bedrock_utils.py', + ], + }, + additionalPrerequisits: [ + 'Access to Amazon Textract and Amazon Comprehend via the AWS CLI', + 'An Amazon S3 bucket with permissions to upload and list objects. This is required to upload your document. Please note the name of the bucket, you will need this.', + ], + extraSteps: [ + { + instructions: + 'Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain your AWS profile, along with the name of your S3 bucket for uploaded documents, as shown below:', + command: ` + profile_name= + save_folder=`, + }, + { + instructions: + 'Since this repository is configured to leverage Claude 3.5 Sonnet, the prompt payload is structured in a different format compared to previous models and other model providers. If you wanted to leverage other Amazon Bedrock models you can change the Bedrock invocation function in each file, modifying the body parameters using this guide depending on the model ID.\nDepending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure each file that utilizes Bedrock set to the appropriate region. Each of these files are configured as shown below:', + command: ` + client = boto3.client("bedrock-runtime", region_name="us-west-2") + model_id = "anthropic.claude-3-5-sonnet-20240620-v1:0"`, + }, + ], + fileWalkthrough: { + includeDefaults: true, + files: [ + { + name: 'pages/welcome.py', + description: + 'The welcome page providing an overview of the Intelligent Document Processing (IDP) stages.', + }, + { + name: 'pages/upload_doc_to_s3.py', + description: + 'The streamlit page that houses the logic to select a document or file to upload.', + }, + { + name: 'pages/extract_text_with_textract.py', + description: + 'The streamlit page that houses the logic to invoke Textract to extract the raw text and key-value pairs from the document.', + }, + { + name: 'pages/enrich_doc_with_bedrock.py', + description: + 'The streamlit page that houses the logic to read the key-value pair text file (output/key_value.txt) and invoke Bedrock to enrich the document by correcting any grammar mistakes or incorrect text extractions from the Textract job. The enriched result is saved as a local text file (output/enriched_output.txt).', + }, + { + name: 'pages/entity_recognition_with_comprehend.py', + description: + 'The streamlit page that houses the logic to invoke Comprehend to perform entitiy recognition on the contents in the enriched output file (output/enriched_output.txt).', + }, + { + name: 'pages/classify_doc_with_bedrock.py', + description: + "The streamlit page that houses the logic to provide the user the option to classify the document from a select category of classes using either Bedrock's text or multimodal capabilities. A user can choose to have Bedrock read the enriched output file (output/enriched_output.txt) or read the file stored in S3 as an image to classify the document.", + }, + { + name: 'pages/summarize_doc_with_bedrock.py', + description: + "The streamlit page that houses the logic to provide the user the option to summarize the document using either Bedrock's text or multimodal capabilities. A user can choose to have Bedrock read the enriched output file (output/enriched_output.txt) or read the file stored in S3 as an image to summarize the document.", + }, + { + name: 'pages/doc_qa_with_bedrock.py', + description: + "The streamlit page that houses the logic to provide the user the option to ask questions about the document using either Bedrock's text or multimodal capabilities. A user can choose to have Bedrock read the enriched output file (output/enriched_output.txt) or read the file stored in S3 as an image to answer user queries regarding the document's contents.", + }, + { + name: 'idp/bedrock_utils.py', + description: + "The file containing the logic for document enrichment, classification, summarization, and question-answering by interacting with Amazon Bedrock. These interactions are performed by sending a structured prompt containing the relevant text or image data to the Bedrock model via API calls. The prompt includes instructions for the model, such as correcting grammar, classifying documents into predefined categories, or summarizing content, and the model's responses are parsed and returned as usable output.", + }, + { + name: 'idp/comprehend_utils.py', + description: + 'The file containing the logic to invoke Amazon Comprehend, which will perform entity recognition using the default pre-trained model to detect entities such as names, dates, organizations, etc.', + }, + { + name: 'idp/s3_utils.py', + description: + 'The file containing the logic to upload a file to S3 and list any current documents stored in the selected bucket.', + }, + { + name: 'idp/textract_utils.py', + description: + 'The file containing the logic to start a Textract job that analyzes the document and extracts the raw text and key-value pairs from the document, saving both as local text files (extracted_text.txt and key_value.txt) to the "output" folder.', + }, + ], + }, + }, +})); + +pythonPocs.push(new StreamlitQuickStartPOC({ + parentProject: project, + pocName: 'Amazon Bedrock Image Generation with Guardrails', + pocPackageName: 'amazon-bedrock-image-guardrails-poc', + pocDescription: 'This sample code demonstrates using Amazon Bedrock Guardrails to prevent Stability Diffusion LLM from generating harmful, obscene, or violent images. The application features a streamlit frontend where users input zero-shot requests to Claude 3. Amazon Bedrock Guardrails determine whether to proceed with generating images using the Stability Diffusion model.', + readme: { + pocGoal: { + overview: `The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to create images based on text input requests with security guardrails. +This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes.`, + architectureImage: true, + flowSteps: [ + 'The user inserts a text question into to the streamlit app. (app.py).', + 'The streamlit app, takes the text inserted by the user and is passed to Claude LLM with Guardrail id to check for prompt which is acceptable. If the prompt is detected as malicious or triggers the guardrail, a response (Blocked Messaging statement on Bedrock Guardrails) will be returned to the end user saying the request is blocked with a message "Inappropriate prompt!!" (image_generation_guardrails.py).', + 'If the prompt does not trigger the guardrail, it is passedto the model Stability diffusion model to generate images.', + ], + }, + additionalPrerequisits: [ + 'Create an Amazon Bedrock Guardrail, information on how to do that can be found [here](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-create.html) ', + ], + fileWalkthrough: { + includeDefaults: true, + files: [{ + name: 'invoke_model_with_guardrails.py', + description: 'the logic of the application, including the Amazon Bedrock Guardrail and Amazon Bedrock API invocations.', + }], + }, + extraSteps: [{ + instructions: 'create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain:', + command: `profile_name= +region_name= +guardrail_identifier= +guardrail_version= (this is just a number i.e. 1,2,3 etc...)`, + }], + }, +})); + +const pythonPocReadmeDetails: Array = []; +for (const poc of pythonPocs) { + pythonPocReadmeDetails.push(poc.readmeDetails); + poc.synth(); +} + + +/** END OF PYTHON POCS */ + +/** + * .NET POCs START + */ + +const dotNetPOCs = new DotNetQuickStartPOCs(); + +dotNetPOCs.addPoc({ + pocName: 'Amazon Bedrock Converse API POC', + pocDescription: 'This repository contains sample code demonstrating various use cases leveraging Amazon Bedrock and Generative AI using Amazon Bedrock SDK for .NET. Each sample is a separate page within a Visual Studio Solutions, and includes a basic Blazor frontend to help users quickly set up a proof of concept.', + imagePath: 'genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Converse.Api.Poc/images/Bedrock-Converse-dot-net.gif', + architectureImage: true, +}); + +dotNetPOCs.addPoc({ + pocName: 'Amazon Bedrock Document Generator POC', + pocDescription: 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to create content for documents.', + imagePath: 'genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Converse.Api.Poc/images/Bedrock-Converse-dot-net.gif', + architectureImage: true, +}); + +dotNetPOCs.addPoc({ + pocName: 'Amazon Bedrock Guardrail POC', + pocDescription: 'This is sample code demonstrating the use of Amazon Bedrock Guardrails to help prevent prompt-injection attacks and prevent unintended responses from the LLM. The application is constructed with a simple ASP.NET Blazor frontend where users can input zero shot requests to Claude 3, with Amazon Bedrock Guardrails in place to prevent malicious prompts and responses.', + imagePath: 'genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Guardrail.Poc/images/bedrock-guardrail-poc.gif', + architectureImage: true, +}); + +dotNetPOCs.addPoc({ + pocName: 'Amazon Bedrock Knowledgebases RAG POC', + pocDescription: 'This repository contains sample code demonstrating various use cases leveraging Amazon Bedrock and Generative AI. Each sample is a separate project with its own directory, and includes a basic Streamlit frontend to help users quickly set up a proof of concept.', + imagePath: 'genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Knowledgebases.Rag.Poc/images/02-rag-with-kb.png', + architectureImage: true, +}); + +dotNetPOCs.addPoc({ + pocName: 'Amazon Bedrock RAG Kendra POC', + pocDescription: 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a RAG based architecture with Amazon Kendra.using Amazon Bedrock SDK for .NET. The application is constructed with a simple blazor front-end where users can ask questions against documents stored in Amazon Kendra.', + imagePath: 'genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Rag.Kendra.Poc/images/demo.png', + architectureImage: true, +}); + +/** + * End .NET POCs + */ + +new READMEComponent(project, 'RootREADME', pythonPocReadmeDetails, dotNetPOCs.dotNetPocs).synthesize(); + +project.synth(); diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d0649a77..e97d7a3f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,6 +38,47 @@ To send us a pull request, please: GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). +## Development Guidelines for Python & .NET POCs +The GenAI QuickStart POCs is managed using [Projen](https://projen.io/) to help ensure a consistent user experience and developer experience. By leveraging Projen, POCs are able to be created in a repeatable manner that ensures both functionliaty and documentation maintains consistency. To add a new POC, you will need to follow the guidance below. + +### Adding a new Python POC +1. In the root of your project, run `npm install` +1. Navigate to `.projenrc.ts` in the root of the repo. +1. At the end of the Python POC definitons, create a new `StreamlitQuickStartPOC` definition that matches your POC needs. + An example of a basic POC definiton: + ```typescript + dotNetPOCs.addPoc({ + pocName: 'Amazon Bedrock Document Generator POC', + pocDescription: 'This is sample code demonstrating the use of Amazon Bedrock and Generative AI to create content for documents.', + imagePath: 'genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Converse.Api.Poc/images/Bedrock-Converse-dot-net.gif', + architectureImage: true, + }); + ``` +1. Define additional README details within the declaration. See [streamlit-quickstart-poc.ts](projenrc/projects/streamlit-quickstart-poc.ts) and review `StreamlitQuickStartPOCProps` for details on all the property values you can provide. +1. Once you have completed your definiton, in your terminal, run + ```shell + npx projen + ``` + This will generate the base POC with the configurations you provided. +1. Complete your POC development in the generated POC folder, updating `app.py` and adding your custom logic modules. +1. Ensure the following files are created: + * `images/demo.gif` - A gif with a screen recording of the POC. + * `images/architecture.png` - a PNG image of the AWS Architecture used for the POC. +1. If you make any updates to the `.projenrc.ts` file, rerun: + ``` + npx projen + ``` + This will regenerate README files. + +### Adding a new .NET POC +1. .NET POCs are less structured in how their are maintained and contributed to. Create the POC in the `genai-quickstart-pocs-dot-net/`. +1. Once the POC is complete, Define .NET POC in the `.projenrc.ts`, which adds the .NET POC definition to the main README doc. +1. In your terminal, run + ``` + npx projen + ``` + This will regenerate the README and the new POC should be added. + ## Finding contributions to work on Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. diff --git a/LICENSE b/LICENSE index 56a66b6b..d6456956 100644 --- a/LICENSE +++ b/LICENSE @@ -1,16 +1,202 @@ -MIT No Attribution - -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - -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. - -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 [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 336fa5cf..876b8465 100644 --- a/README.md +++ b/README.md @@ -2,143 +2,266 @@ This repository contains sample code demonstrating various use cases leveraging Amazon Bedrock and Generative AI. Each sample is a separate project with its own directory, and includes a basic Streamlit frontend to help users quickly set up a proof of concept. -##### Authors: Brian Maguire, Dom Bavaro, Ryan Doty, Sudeesh Sasidharan, Tarik Makota +##### Authors: Brian Maguire, Dom Bavaro, Ryan Doty, Sudeesh Sasidharan, Tarik Makota, Addie Rudy ## Sample Proof of Concepts - Python -1. **Amazon-Bedrock-Summarization-Long-Document-POC:** - This sample demonstrates using Amazon Bedrock and Generative AI to implement a long document summarization use case. Users can upload large PDF documents, which are chunked and summarized using Amazon Bedrock. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/images/demo.gif) -2. **Amazon-Bedrock-RAG-OpenSearchServerless-POC:** - This sample demonstrates creating custom embeddings stored in Amazon OpenSearch Serverless, and answering questions against the indexed embeddings using a Retrieval-Augmented Generation (RAG) architecture with Amazon Bedrock. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/images/demo.gif) -3. **Amazon-Bedrock-RAG-Kendra-POC:** - This sample implements a RAG-based architecture with Amazon Kendra, allowing users to ask questions against documents stored in an Amazon Kendra index using Amazon Bedrock. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/images/demo.gif) -4. **Amazon-Bedrock-Image-Generation-POC:** - This sample demonstrates using Amazon Bedrock and Generative AI to generate images based on text input requests. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/images/demo.gif) -5. **Amazon-Bedrock-GenAI-Dynamic-Prompting-Explained-POC:** - This sample provides a hands-on explanation of how dynamic prompting works in relation to Generative AI, using Amazon Bedrock. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/images/demo.gif) -6. **Amazon-Bedrock-Document-Generator:** - This sample demonstrates using Amazon Bedrock and Generative AI to perform document generation based on a document template and user-provided details. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/images/demo.gif) -7. **Amazon-Bedrock-Document-Comparison-POC:** - This sample allows users to upload two PDF documents and get a list of all changes between them using Amazon Bedrock and Generative AI. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/images/demo.gif) -8. **Amazon-Bedrock-Claude3-Multi-Modal-Sample:** - This sample showcases the multi-modal capabilities of Amazon Bedrock (specifically Anthropic Claude 3), allowing users to input text questions, images, or both to get comprehensive descriptions or answers. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/images/demo.gif) -9. **Amazon-Bedrock-Chat-POC:** - This sample provides a ChatGPT alternative using Amazon Bedrock and Generative AI, allowing users to ask zero-shot questions and receive responses. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-chat-poc/images/demo.gif) -10. **Amazon-Bedrock-Amazon-Redshift-POC:** - This sample demonstrates using Amazon Bedrock and Generative AI to ask natural language questions and transform them into SQL queries against Amazon Redshift databases. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/images/demo.gif) -11. **Amazon-Bedrock-Amazon-RDS-POC:** - This sample allows users to ask natural language questions and transform them into SQL queries against Amazon RDS databases using Amazon Bedrock and Generative AI. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/images/demo.gif) -12. **Amazon-Bedrock-Amazon-Athena-POC:** - This sample demonstrates using Amazon Bedrock and Generative AI to ask natural language questions and transform them into SQL queries against Amazon Athena databases. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/images/demo.gif) -13. **Amazon-Bedrock-Streaming-Response-POC:** - This sample illustrates the utilization of Amazon Bedrock and Generative AI to implement streaming responses. The application is designed with a straightforward Streamlit frontend, enabling users to input zero-shot requests directly against the Large Language Model (LLM) of their choice, utilizing a streaming response technique with majority of Amazon Bedrock models. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/images/demo.gif) -14. **Amazon-Bedrock-Claude3-Streaming-Response-POC:** - This sample illustrates the utilization of Amazon Bedrock and Generative AI to implement streaming responses. The application is designed with a straightforward Streamlit frontend, enabling users to input zero-shot requests directly against Claude 3, utilizing a streaming response technique while leveraging the Anthropic Messages API structure. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/images/demo.gif) -15. **Amazon-Bedrock-Knowledgebases-RAG-POC:** - This sample implements a RAG-based architecture with Amazon Bedrock Knowledge Bases, allowing users to ask questions against documents stored in an Amazon Bedrock Knowledge Base using Amazon Bedrock. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/images/demo.gif) -16. **Amazon-Bedrock-Langchain-RAG-POC:** - This sample implements a RAG-based architecture with Amazon Bedrock Knowledge Bases using Langchain to help orchestrate the retrieval of information from the knowledge base. This allows users to ask questions against documents stored in an Amazon Bedrock Knowledge Base using Amazon Bedrock, and Langchain as an orchestrator. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/images/demo.gif) -17. **Amazon-Bedrock-Asynchronous-Invocation-POC:** - This sample implements asynchronous invocations with Amazon Bedrock allowing users to make multiple simultaneous calls to Bedrock models to decrease overall latency. This allows users to ask questions against 3+ models simultaneously, demonstrating the decrease in latency by doing it asynchronously vs sequentially. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/images/demo.gif) -18. **Amazon-Bedrock-Model-Playground-POC:** - This sample implements an Amazon Bedrock Gen AI Model playground that allows users to select any LLM offered by Amazon Bedrock and ask zero shot questions directly against it. This provides business users the ability to experiment with different Amazon Bedrock LLMs without having access to the AWS console. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/images/demo.gif) -19. **Amazon-Bedrock-Claude3-Image-Analysis-POC:** - This sample implements an image analysis app that uses Amazon Bedrock and Claude3 to collect data from an image and return as JSON. This provides users the ability to quickly experiment with image analysis use-cases and customize the JSON response to the needs of their image analysis use-case. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/images/demo.gif) -20. **Amazon-Bedrock-Guardrails-POC** - This sample implements Amazon Bedrock Guardrails to demonstrate how you can leverage guardrails to prevent malicious prompts and repsonse from your generative AI applications built with Amazon Bedrock. - ![Alt text](genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/images/demo.gif) -21. **Amazon-Bedrock-Video-Chapter-Search-POC:** - This is sample code demonstrating the use of Amazon Transcribe, Amazon Bedrock and Generative AI, to implement a video chapter generator and video search sample. - ![Amazon Bedrock Video Chapter Creator POC Demo](genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/images/demo.gif) -22. **Amazon-Bedrock-Model-Customization-POC** - The sample notebooks provide guidance on fine-tuning and pre-training models in Bedrock. - The sample data used in the notebooks can be replaced with any data in csv files to create fine-tuned and pre-trained models using Amazon Titan Express as the base model. -23. **Amazon-Bedrock-Speech-to-Text-Chat-POC:** - This sample provides a ChatGPT alternative using Amazon Transcribe, Amazon Polly, Amazon Bedrock and Generative AI, allowing users to ask zero-shot questions using speech-to-text prompts and listen to responses. - ![Amazon Bedrock Speech-to-Text Chat Demo](genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/images/demo.gif) -24. **Amazon-Bedrock-CSV-Chatbot-POC:** - This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a chatbot is able to converse with the user based on CSV data provided by the user. - ![Amazon Bedrock CSV Chatbot Demo](genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/images/demo.gif) -25. **Amazon-Bedrock-Translation-POC:** + + +1. **Amazon Bedrock Alt Text Generator** + This POC demonstrates how to use the Amazon Bedrock Alt Text Generator to generate alt text for images in PDF documents. + + +1. **Amazon Bedrock Amazon Athena POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to use natural language questions to query relational data stores, specifically Amazon Athena. This example leverages the MOMA Open Source Database: https://github.com/MuseumofModernArt/collection. + + ![Screen Recording of Amazon Bedrock Amazon Athena POC](genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/images/demo.gif) + + +1. **Amazon Bedrock & Amazon RDS POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to use natural language questions to query relational data stores, specifically Amazon RDS. This example leverages the MOMA Open Source Database: https://github.com/MuseumofModernArt/collection. + + ![Screen Recording of Amazon Bedrock & Amazon RDS POC](genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/images/demo.gif) + + +1. **Amazon Bedrock & Amazon Redshift POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to use natural language questions to query relational data stores, specifically Amazon Redshift. This example leverages the MOMA Open Source Database: https://github.com/MuseumofModernArt/collection. + + **Please Note: If you don't want to build this from scratch, Amazon Redshift now supports GenAI capabilities natively, more information on that can be found [here](https://aws.amazon.com/blogs/aws/amazon-redshift-adds-new-ai-capabilities-to-boost-efficiency-and-productivity/).** + + ![Screen Recording of Amazon Bedrock & Amazon Redshift POC](genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/images/demo.gif) + + +1. **Amazon Bedrock Asynchronous Invocation POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to perform asynchronous invocations of large language models. The application is constructed with a simple streamlit frontend where users can input zero shot requests directly against the LLM of their choice, leveraging asynchronous invocations, to invoke 3 models simultaneously to reduce overall latency. + + ![Screen Recording of Amazon Bedrock Asynchronous Invocation POC](genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/images/demo.gif) + + +1. **Amazon Bedrock Chat POC** + Amazon Bedrock Chat POC + + ![Screen Recording of Amazon Bedrock Chat POC](genai-quickstart-pocs-python/amazon-bedrock-chat-poc/images/demo.gif) + + +1. **Amazon Bedrock Claude 3 Image Analysis POC** + This is sample code demonstrating the use of Amazon Bedrock and Multi-Modal Generative AI models from Anthropic to implement an image analysis use case. The application is constructed with a simple streamlit frontend where users can upload a 1 page jpeg, png or PDF and get a description of the image. + + ![Screen Recording of Amazon Bedrock Claude 3 Image Analysis POC](genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/images/demo.gif) + + +1. **Amazon Bedrock Claude 3 Long Form Output POC** This is sample code demonstrating the use of Amazon Bedrock and Generative AI to translate text from a source to target language. - ![Amazon Bedrock Translation Demo](genai-quickstart-pocs-python/amazon-bedrock-translation-poc/images/demo.gif) -26. **Amazon-Bedrock-Meeting-Minutes-Summarization-POC:** - This code demonstrates using Amazon Bedrock and Amazon Transcribe to generate summarized meeting minutes and key action items. It accepts meeting recordings in formats like mp4, wav, mp4a and txt as input. It then processes these recordings and outputs a text summarizing the key discussion points and action items from the meeting. This summary text can be downloaded as .txt file for review and sharing. - ![Amazon-Bedrock-Meeting-Minutes-Summarization Demo](genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/images/demo.gif) -27. **Amazon-Bedrock-Converse-API-POC:** - This sample poc demonstrates how to use the Amazon Bedrock converse API to facilitate conversational GenAI use cases. The key feature it demonstrates is how the Amazon Bedrock Converse API is able to retain chat history to provide context aware responses to end users. - ![Amazon-Bedrock-Converse-API-POC](genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/images/demo.gif) -28. **Amazon-Bedrock-Converse-Stream-API-POC:** - This sample poc demonstrates how to use the Amazon Bedrock ConverseStream API to facilitate conversational GenAI use cases. The key feature it demonstrates is how the Amazon Bedrock ConverseStream API provides streaming capabilities to improve end users experience. ConverseStream API is able to retain chat history to provide context aware responses to end users. - ![Amazon-Bedrock-Converse-Stream-API-POC](genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/images/demo.gif) -29. **Amazon-Bedrock-Model-Eval-POC:** - This is sample code aimed to accelerate customers aiming to leverage [Amazon Bedrock Model Evaluator](https://docs.aws.amazon.com/bedrock/latest/userguide/model-evaluation.html) with custom prompt data. This Proof-of-Concept (POC) enables users to provide a CSV containing data that should be used with Amazon Bedrock Model Evaluator. - ![Amazon Bedrock Model Evalutor Data Creator POC](genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/images/demo.gif) -30. **Amazon-Bedrock-Text-Extraction-POC:** - This is a sample proof of concept demonstrating how customers can leverage large language models to perform text extraction use cases. - ![Amazon Bedrock Claude3 Long Form Output POC](genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/images/demo.gif) -31. **Amazon-Bedrock-Claude3-Long-Form-Output-POC:** - This is sample code aimed to accelerate customers aiming to handle long form output using Claude3. - ![Amazon Bedrock Claude3 Long Form Output POC](genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/images/demo.gif) -32. **Amazon-Bedrock-Task-Classification:** - This sample code demonstrates how to use Amazon Bedrock and Generative AI to implement a task classification bot. The application allows a user to input a task and get the correct classification which then trigger appropriate downstream workflows to process the task inputted. - ![Amazon-Bedrock-Task-Classification](genai-quickstart-pocs-python/amazon-bedrock-task-classification/public/demo.gif) -33. **Amazon-Bedrock-Alt-Text-Generator:** - This sample code demonstrates how to use Amazon Bedrock and Generative AI to create Alt text for all images within a PDF, helping improve accessibility at scale. - ![Amazon-Bedrock-Alt-Text-Generator](genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/images/demo.gif) -34. **Amazon-Bedrock-Semantic-Cache:** - This sample code demonstrates a Retrieval-Augmented Generation (RAG) system using Amazon Bedrock for knowledge retrieval and OpenSearch for semantic caching. - ![Amazon-Bedrock-Semantic-Cache](genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/SemanticCache.gif) -35. **Amazon-Bedrock-PowerPoint-Generator** + + ![Screen Recording of Amazon Bedrock Claude 3 Long Form Output POC](genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/images/demo.gif) + + +1. **Amazon Bedrock Claude 3 Multi-Modal POC** + This is sample code demonstrating the use of Amazon Bedrock and Anthropic Claude 3 to satisfy multi-modal use cases. The application is constructed with a simple streamlit frontend where users can input zero shot requests to satisfy a broad range of use cases, including image to text multi-modal style use cases. + + ![Screen Recording of Amazon Bedrock Claude 3 Multi-Modal POC](genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/images/demo.gif) + + +1. **Amazon Bedrock Claude 3 Streaming Response POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement streaming responses. The application is constructed with a simple streamlit frontend where users can input zero shot requests directly against the LLM of their choice, leveraging a streaming response technique. + + +1. **Amazon Bedrock Converse API POC** + This is sample code demonstrating the use of the Amazon Bedrock Converse API to help with conversation oriented use cases that require context preservation. The application is constructed with a simple streamlit frontend where users can input zero shot requests to Claude 3, with the Amazon Bedrock Converse API in place to allow users to ask context aware questions. + + ![Screen Recording of Amazon Bedrock Converse API POC](genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/images/demo.gif) + + +1. **Amazon Bedrock Converse Stream API POC** + This is sample code demonstrating the use of the Amazon Bedrock ConverseStream API to help with conversation oriented use cases that require context preservation. The application is constructed with a simple streamlit frontend where users can input zero shot requests to Claude 3, with the Amazon Bedrock ConverseConverseStream API in place to allow users to ask context aware questions and stream the response back. + + ![Screen Recording of Amazon Bedrock Converse Stream API POC](genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/images/demo.gif) + + +1. **Amazon Bedrock CSV Chatbot POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a chatbot is able to converse with the user based on CSV data provided by the user. The application is constructed with a simple streamlit frontend where users can upload large CSV files and get them analyzed or start chatbot interactions. + + ![Screen Recording of Amazon Bedrock CSV Chatbot POC](genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/images/demo.gif) + + +1. **Amazon Bedrock Document Comparison POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a document comparison use case. The application is constructed with a simple streamlit frontend where users can upload 2 versions of a document and get all changes between documents listed. + + ![Screen Recording of Amazon Bedrock Document Comparison POC](genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/images/demo.gif) + + +1. **Aamazon Bedrock Document Generator POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a document generation use case. The application is constructed with a simple streamlit frontend where users can provide details and create a document in the exact format that the you specify. + + ![Screen Recording of Aamazon Bedrock Document Generator POC](genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/images/demo.gif) + + +1. **Amazon Bedrock GenAI Dynamic Prompt Explained POC** + This is sample code that can be used to provide a hands on explanation as to how Dynamic Prompting works in relation to Gen AI. The application is constructed with a simple streamlit frontend where users can ask questions against a Amazon Bedrock supported LLM and get a deeper understanding of how few-shot and dynamic prompting works. + + ![Screen Recording of Amazon Bedrock GenAI Dynamic Prompt Explained POC](genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/images/demo.gif) + + +1. **Amazon Bedrock Guardrails POC** + This is sample code demonstrating the use of Amazon Bedrock Guardrails to help prevent prompt-injection attacks and prevent unintended responses from the LLM. The application is constructed with a simple streamlit frontend where users can input zero shot requests to Claude 3, with Amazon Bedrock Guardrails in place to prevent malicious prompts and responses. + + ![Screen Recording of Amazon Bedrock Guardrails POC](genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/images/demo.gif) + + +1. **Amazon Bedrock Image Generation POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement an image generation use case. The application is constructed with a simple streamlit frontend where users can input text requests to generate images based on the text input. + + ![Screen Recording of Amazon Bedrock Image Generation POC](genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/images/demo.gif) + + +1. **Amazon Bedrock Knowledgebases RAG POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to create vector embeddings for your data sources using Amazon Bedrock Knowledge bases with the ability ask questions against the stored documents. The application is constructed with a RAG based architecture where users can ask questions against the Knowledge bases. + + +1. **Amazon Bedrock LangChain RAG POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI using Langchain as orchestrator with the ability ask questions against the stored documents. This sample uses Knowledge bases as to retrieve the stored documents, however you can extend or update this sample to retrieve your stored documents from any Vector DB. + + ![Screen Recording of Amazon Bedrock LangChain RAG POC](genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/images/demo.gif) + + +1. **Amazon Bedrock Meeting Minutes Summarization POC** + This application demonstrates using Amazon Bedrock and Amazon Transcribe to summarize meeting recordings. The streamlit frontend allows users to upload audio, video, or text files of meeting recording. Amazon Transcribe generates a transcript of recording and sent it Amazon Bedrock for summarization of the key discussion points. Users can then download the generated summarized meeting notes. + + ![Screen Recording of Amazon Bedrock Meeting Minutes Summarization POC](genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/images/demo.gif) + + +1. **Amazon Bedrock Model Customization** + This sample leverages Jupyter Notebooks to demonstrate how to customize bedrock models. + + +1. **Amazon Bedrock Model Evaluation Data Prep Tool** + This is sample code aimed to accelerate customers aiming to leverage [Amazon Bedrock Model Evaluator](https://docs.aws.amazon.com/bedrock/latest/userguide/model-evaluation.html) with custom prompt data. This Proof-of-Concept (POC) enables users to provide a CSV containing data that should be used with Amazon Bedrock Model Evaluator. The user then maps the CSV columns to the appropriate fields depending on which type of Model Evaluation being executed. This will generate one or more `.jsonl` formatted files, ready for use with Amazon Bedrock Model Evaluator. + + +1. **Amazon Bedrock Model Playground POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a Gen AI model playground. The application is constructed with a simple streamlit frontend where users can input zero shot requests and select any LLM offered by Amazon Bedrock. + + ![Screen Recording of Amazon Bedrock Model Playground POC](genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/images/demo.gif) + + +1. **Amazon Bedrock RAG with Kendra POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a RAG based architecture with Amazon Kendra. The application is constructed with a simple streamlit frontend where users can ask questions against documents stored in Amazon Kendra. + + ![Screen Recording of Amazon Bedrock RAG with Kendra POC](genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/images/demo.gif) + + +1. **Amazon Bedrock RAG with OpenSearch Serverless POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to create custom embeddings stored in Amazon OpenSearch Serverless with the ability ask questions against the stored documents. The application is constructed with a RAG based architecture where users can ask questions against the indexed embeddings within OpenSearch Serverless. + + ![Screen Recording of Amazon Bedrock RAG with OpenSearch Serverless POC](genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/images/demo.gif) + + +1. **Amazon Bedrock Semantic Cache POC** + This project demonstrates a Retrieval-Augmented Generation (RAG) system using Amazon Bedrock for knowledge retrieval and OpenSearch for semantic caching. It provides a Streamlit-based user interface for asking questions about data stored in Amazon Knowledge Bases. + + ![Screen Recording of Amazon Bedrock Semantic Cache POC](genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/demo.gif) + + +1. **Amazon Bedrock Speech to Text POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a ChatGPT alternative using speech-to-text prompts. The application is constructed with a simple streamlit frontend where users can provide zero shot requests using their computer’s microphone and listen to responses to satisfy a broad range of use cases. + + ![Screen Recording of Amazon Bedrock Speech to Text POC](genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/images/demo.gif) + + +1. **Amazon Bedrock Streaming Response POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement streaming responses. The application is constructed with a simple streamlit frontend where users can input zero shot requests directly against the LLM of their choice, leveraging a streaming response technique. + + ![Screen Recording of Amazon Bedrock Streaming Response POC](genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/images/demo.gif) + + +1. **Amazon Bedrock Summarization of Long Documents POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a long document summarization use case. The application is constructed with a simple streamlit frontend where users can upload large documents and get them summarized. + + ![Screen Recording of Amazon Bedrock Summarization of Long Documents POC](genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/images/demo.gif) + + +1. **Amazon Bedrock Task Classification POC** + This sample code demonstrates how to use Amazon Bedrock and Generative AI to implement a task classification bot. The application is constructed with a simple streamlit frontend where users can input a task and get the correct classification which then trigger appropriate downstream workflows to process the task inputted. + + ![Screen Recording of Amazon Bedrock Task Classification POC](genai-quickstart-pocs-python/amazon-bedrock-task-classification/images/demo.gif) + + +1. **Amazon Bedrock Text Extraction POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to extract text from a document. The application is constructed with a simple streamlit frontend where users leverage Bedrock Agents to extract and summarize key information from a document like a financial earnings report. + + ![Screen Recording of Amazon Bedrock Text Extraction POC](genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/images/demo.gif) + + +1. **Amazon Bedrock Translation POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to translate text from a source to target language. + + ![Screen Recording of Amazon Bedrock Translation POC](genai-quickstart-pocs-python/amazon-bedrock-translation-poc/images/demo.gif) + + +1. **Amazon Bedrock Video Chapter Creator POC** + This is sample code demonstrating the use of Amazon Transcribe, Amazon OpenSearch Serverless, Amazon Bedrock and Generative AI, to a implement video chapter generator and video search sample. + The application is constructed with a simple streamlit frontend where users can upload a video that will be stored, transcribed and have searchable chapters generated. Additionally, if you have videos already uploaded to S3 and have subtitles for the video already created in `.srt` format, you can skip transcribing and jump straight into generating chapters. + + + The sample also includes a second UI that allows the user to ask about a topic. This will search the video chapters from the videos you've provided and provide a video, set to a specific chapter, that was the closest match to the inquiry. + + ![Screen Recording of Amazon Bedrock Video Chapter Creator POC](genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/images/demo.gif) + + +1. **Amazon Bedrock PowerPoint Generator** This is sample code demonstrates the use of Amazon Bedrock and Generative AI to implement a PowerPoint generator. The application is constructed with a simple streamlit frontend where users can input a topic and get a PowerPoint generated based on the topic. Using Generative AI, the solution creates relevant Wikipedia queries to perform in-depth research on the presentation content. - ![Amazon-Bedrock-PowerPoint-Generator](genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/images/demo.gif) -36. **Amazon-Bedrock-Intelligent-Document-Processing:** - This is sample code demonstrating the use of Amazon Bedrock and Generative AI incorporated into an Intelligent Document Processing (IDP) pipeline using user-uploaded documents. The application is constructed with a simple streamlit frontend where users can upload various document formats and perform different IDP actions such as text extraction, document summarization and classification, entity recognition, and Q&A to satisfy a broad range of use cases. - ![Amazon-Bedrock-PowerPoint-Generator](genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/images/demo.gif) -37. **Amazon-Bedrock-Quiz-Generator-POC** - This is sample code demonstrates the use of Amazon Bedrock and Generative AI to implement a Quiz Generator. The application is constructed with a simple streamlit frontend where users can upload one or more documents (`.pdf`, `.docx`, `.doc`, `.csv`, `.md`, `.png`, `.jpg`) and generate a quiz with anywhere from 5 to 100 questions (multi-choice / true or false). - ![Amazon-Bedrock-Quiz-Generator](genai-quickstart-pocs-python/amazon-bedrock-quiz-generator-poc/images/demo.gif) + +1. **Amazon Bedrock Intelligent Document Processing (IDP) POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI incorporated into an Intelligent Document Processing (IDP) pipeline using user-uploaded documents. The application is constructed with a simple streamlit frontend where users can upload various document formats and perform different IDP actions such as text extraction, document summarization and classification, entity recognition, and Q&A to satisfy a broad range of use cases. + + ![Screen Recording of Amazon Bedrock Intelligent Document Processing (IDP) POC](genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/images/demo.gif) + +1. **Amazon Bedrock Image Generation with Guardrails** + This sample code demonstrates using Amazon Bedrock Guardrails to prevent Stability Diffusion LLM from generating harmful, obscene, or violent images. The application features a streamlit frontend where users input zero-shot requests to Claude 3. Amazon Bedrock Guardrails determine whether to proceed with generating images using the Stability Diffusion model. + + ![Screen Recording of Amazon Bedrock Image Generation with Guardrails](genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/images/demo.gif) + ## Sample Proof of Concepts - .NET -1. **Amazon-Bedrock-Summarization-Long-Document-POC:** - Amazon-Bedrock-Document-Generator: This sample demonstrates using Amazon Bedrock and Generative AI to perform document generation based on a document template and user-provided details. - ![Amazon Bedrock Document Generator](genai-quickstart-pocs-dot-net/images/text-generation.png) -2. **Amazon-Bedrock-Knowledgebases-RAG-POC:** - This sample implements a RAG-based architecture with Amazon Bedrock Knowledge Bases, allowing users to ask questions against documents stored in an Amazon Bedrock Knowledge Base using Amazon Bedrock. - ![Amazon Bedrock Knowledgebases RAG](genai-quickstart-pocs-dot-net/images/rag-with-kb.png) -3. **Amazon-Bedrock-Kendra-RAG-POC:** - This sample implements a RAG-based architecture with Amazon Kendra, allowing users to ask questions against documents stored in a Kendra index and allowing users to do q&a using Amazon Bedrock models. - ![Amazon-Bedrock-Kendra-RAG](genai-quickstart-pocs-dot-net/images/rag-with-kendra.png "RAG with Kendra") -4. **Amazon-Bedrock-Converse-API-POC:** - This is sample code demonstrating the use of the Amazon Bedrock Converse API to create conversational applications that send and receive messages to and from an Amazon Bedrock mod l - ![Amazon-Bedrock-Converse-API](genai-quickstart-pocs-dot-net/images/Bedrock-Converse-dot-net.gif "Converse API") -5. **Amazon-Bedrock-Guardrails-POC:** - This is sample code demonstrating the use of Amazon Bedrock Guardrails to help prevent prompt-injection attacks and prevent unintended responses from the LLM. The application is constructed with a simple ASP.NET Blazor frontend where users can input zero shot requests to Claude 3, with Amazon Bedrock Guardrails in place to prevent malicious prompts and responses. - ![Amazon-Bedrock-Guardrails-POC](genai-quickstart-pocs-dot-net/images/bedrock-guardrail-poc.gif) + + +1. **Amazon Bedrock Converse API POC** + This repository contains sample code demonstrating various use cases leveraging Amazon Bedrock and Generative AI using Amazon Bedrock SDK for .NET. Each sample is a separate page within a Visual Studio Solutions, and includes a basic Blazor frontend to help users quickly set up a proof of concept. + + ![Screen Recording of Amazon Bedrock Converse API POC](genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Converse.Api.Poc/images/Bedrock-Converse-dot-net.gif) + + +1. **Amazon Bedrock Document Generator POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to create content for documents. + + ![Screen Recording of Amazon Bedrock Document Generator POC](genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Converse.Api.Poc/images/Bedrock-Converse-dot-net.gif) + + +1. **Amazon Bedrock Guardrail POC** + This is sample code demonstrating the use of Amazon Bedrock Guardrails to help prevent prompt-injection attacks and prevent unintended responses from the LLM. The application is constructed with a simple ASP.NET Blazor frontend where users can input zero shot requests to Claude 3, with Amazon Bedrock Guardrails in place to prevent malicious prompts and responses. + + ![Screen Recording of Amazon Bedrock Guardrail POC](genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Guardrail.Poc/images/bedrock-guardrail-poc.gif) + + +1. **Amazon Bedrock Knowledgebases RAG POC** + This repository contains sample code demonstrating various use cases leveraging Amazon Bedrock and Generative AI. Each sample is a separate project with its own directory, and includes a basic Streamlit frontend to help users quickly set up a proof of concept. + + ![Screen Recording of Amazon Bedrock Knowledgebases RAG POC](genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Knowledgebases.Rag.Poc/images/02-rag-with-kb.png) + + +1. **Amazon Bedrock RAG Kendra POC** + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a RAG based architecture with Amazon Kendra.using Amazon Bedrock SDK for .NET. The application is constructed with a simple blazor front-end where users can ask questions against documents stored in Amazon Kendra. + + ![Screen Recording of Amazon Bedrock RAG Kendra POC](genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Rag.Kendra.Poc/images/demo.png) + + + + ## Prerequisites - Python diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Amazon.Bedrock.Document.Ggenerator.Poc.csproj b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Amazon.Bedrock.Document.Ggenerator.Poc.csproj similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Amazon.Bedrock.Document.Ggenerator.Poc.csproj rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Amazon.Bedrock.Document.Ggenerator.Poc.csproj diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/App.razor b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/App.razor similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/App.razor rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/App.razor diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/Layout/MainLayout.razor b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/Layout/MainLayout.razor similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/Layout/MainLayout.razor rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/Layout/MainLayout.razor diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/Layout/NavMenu.razor b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/Layout/NavMenu.razor similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/Layout/NavMenu.razor rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/Layout/NavMenu.razor diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/Pages/DocumentGeneratorForm.razor b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/Pages/DocumentGeneratorForm.razor similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/Pages/DocumentGeneratorForm.razor rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/Pages/DocumentGeneratorForm.razor diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/Pages/Home.razor b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/Pages/Home.razor similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/Pages/Home.razor rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/Pages/Home.razor diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/Routes.razor b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/Routes.razor similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/Routes.razor rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/Routes.razor diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/_Imports.razor b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/_Imports.razor similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Components/_Imports.razor rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Components/_Imports.razor diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Data/01-doc-template.txt b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Data/01-doc-template.txt similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Data/01-doc-template.txt rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Data/01-doc-template.txt diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/LICENSE b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/LICENSE similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/LICENSE rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/LICENSE diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Program.cs b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Program.cs similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Program.cs rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Program.cs diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Properties/launchSettings.json b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Properties/launchSettings.json similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Properties/launchSettings.json rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Properties/launchSettings.json diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Readme.md b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Readme.md similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/Readme.md rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/Readme.md diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/appsettings.Development.json b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/appsettings.Development.json similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/appsettings.Development.json rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/appsettings.Development.json diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/appsettings.json b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/appsettings.json similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/appsettings.json rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/appsettings.json diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/images/01-document-generator.png b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/images/01-document-generator.png similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/images/01-document-generator.png rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/images/01-document-generator.png diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/images/architecture.png b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/images/architecture.png similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/images/architecture.png rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/images/architecture.png diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/images/demo.gif b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/images/demo.gif similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/images/demo.gif rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/images/demo.gif diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/wwwroot/app.css b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/wwwroot/app.css similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/wwwroot/app.css rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/wwwroot/app.css diff --git a/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/wwwroot/favicon.ico b/genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/wwwroot/favicon.ico similarity index 100% rename from genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Ggenerator.Poc/wwwroot/favicon.ico rename to genai-quickstart-pocs-dot-net/Genai.Quickstart.Pocs/Amazon.Bedrock.Document.Generator.Poc/wwwroot/favicon.ico diff --git a/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.projen/deps.json new file mode 100644 index 00000000..b5a2a8f7 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.projen/deps.json @@ -0,0 +1,56 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "langchain-aws", + "type": "runtime" + }, + { + "name": "langchain-community", + "version": "^0.2", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.2", + "type": "runtime" + }, + { + "name": "pillow", + "type": "runtime" + }, + { + "name": "pymupdf", + "type": "runtime" + }, + { + "name": "pypdf", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "reportlab", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/README.md b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/README.md index 813c6f6c..02635c56 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/README.md @@ -1,57 +1,60 @@ -# PDF Image Alt Text Generator +# Amazon Bedrock Alt Text Generator ## Overview of Solution -The PDF Image Alt Text Generator is a solution designed to extract, analyze, and generate alternative text for images within PDF documents. This solution leverages AWS services and various Python libraries to provide a high-performance and scalable way to enhance PDF accessibility. +This POC demonstrates how to use the Amazon Bedrock Alt Text Generator to generate alt text for images in PDF documents. + +![A gif of a screen recording show casing the Amazon Bedrock Alt Text Generator functionality](images/demo.gif) -![Alt text](images/demo.gif) # How to use this Repo: ## Prerequisites: -1. Amazon Bedrock Access and CLI Credentials. Ensure the AWS credentials have access to execute Amazon Bedrock Model Evaluation. -2. Ensure Python 3.11 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). - -## Step 1: +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -The first step of utilizing this repo is performing a git clone of the repository. +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open the repo in your favorite code editor. Navigate to this POC folder within the repo. -The POC consists of two files: -* `app.py` is the frontend application that is run using streamlit -* `pdf_image_alt_text_generator/generator.py` is the logic that extracts the data from PDF and calls the Bedrock Model for inference -* `pdf_image_alt_text_generator/download_results.py` generates a PDF with all images and their alt text results, as well as input/output token usage, calculated in a table. -## Step 2: +## Steps +1. Clone the repository to your local machine. -Set up a python virtual environment in the directory of the POC and ensure that you are using Python 3.11. This can be done by running the following commands: (make sure you've set your working directory in terminal to the POC directory) + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `pdf_image_alt_text_generator/generator.py` - The is the logic that extracts the data from PDF and calls the Bedrock Model for inference + + * `pdf_image_alt_text_generator/download_results.py` - generates a PDF with all images and their alt text results, as well as input/output token usage, calculated in a table. + + -```zsh -pip install virtualenv -python3.11 -m venv venv -``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -```zsh -source venv/bin/activate -``` +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator + ``` -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -```zsh -pip install -r requirements.txt -``` +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -## Step 4: -Your machine should now be configured to run the POC. To start the POC, execute the following from the command line (from the POC directory, with the virtual environment activated): +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -```zsh -streamlit run app.py -``` -This should start the POC and open a browser window to the application. Follow the instructions in the application to generate prompt data. \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/requirements.txt index a6fed6fb..ad65dbc4 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-alt-text-generator/requirements.txt @@ -1,8 +1,12 @@ -langchain==0.2.13; -langchain-community ==0.2.12; -pypdf == 4.3.1; -streamlit == 1.37.1; -pillow == 10.4.0; -pymupdf == 1.24.9; -reportlab == 4.2.2; -langchain-aws == 0.1.17; \ No newline at end of file +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +langchain-aws +langchain-community>=0.2.0, <0.3.0 +langchain>=0.2.0, <0.3.0 +pillow +pymupdf +pypdf +python-dotenv +reportlab +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/README.md index ec460838..0cf2d199 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/README.md @@ -1,113 +1,101 @@ -# Amazon-Bedrock-Amazon-Athena-POC +# Amazon Bedrock Amazon Athena POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to use natural language questions to query relational data stores, specifically Amazon Athena. This example leverages the MOMA Open Source Database: https://github.com/MuseumofModernArt/collection. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Amazon Athena POC functionality](images/demo.gif) + -The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to take natural language questions, and transform them into relational database queries against Amazon Athena. -This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. +## Goal of this POC +The goal of this POC is to provide users with the abilitity to use Amazon Bedrock and generative AI to take natural language questions and transform them into relational database querties against Amazon Athena. +The POC comes with a basic frontend to help users stand up a proof-of-concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: +When a user interacts with the POC, the flow is as follows: 1. The user makes a request, asking a natural language question based on the database available in Amazon Athena to the GenAI app (app.py). -2. This natural language question is passed into Amazon Bedrock, which takes the natural language question and creates a SQL query (amazon_athena_bedrock_query.py). -3. The created SQL query is then executed against your Amazon Athena database to begin retrieving the data (amazon_athena_bedrock_query.py). -4. The data is retrieved from your Amazon Athena Database and is passed back into Amazon Bedrock, to generate a natural language answer based on the retrieved data (amazon_athena_bedrock_query.py). -5. The LLM returns a natural language response to the user through the streamlit frontend based on the retrieved data (app.py). -# How to use this Repo: +1. This natural language question is passed into Amazon Bedrock, which takes the natural language question and creates a SQL query (amazon_athena_bedrock_query.py). -## Prerequisites: +1. The created SQL query is then executed against your Amazon Athena database to begin retrieving the data (amazon_athena_bedrock_query.py). -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Amazon Athena Access and the ability to create a Amazon Athena database and tables. -3. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3100/). -4. Please note that this project leverages the [langchain-experimental](https://pypi.org/project/langchain-experimental/) package which has known vulnerabilities. +1. The data is retrieved from your Amazon Athena Database and is passed back into Amazon Bedrock, to generate a natural language answer based on the retrieved data (amazon_athena_bedrock_query.py). -## Step 1: +1. The LLM returns a natural language response to the user through the streamlit frontend based on the retrieved data (app.py). -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open it up in your favorite code editor.The file structure of this repo is broken into 4 key files, -the app.py file, the amazon_athena_bedrock_query.py file, the moma_examples.yaml file, and the requirements.txt. The app.py file houses the frontend application (streamlit app). -The amazon_athena_bedrock_query.py file contains connectors into your Amazon Athena database and the interaction with Amazon Bedrock through LangChains SQLDatabaseChain. -The moma_examples.yaml file contains several samples prompts that will be used to implement a few-shot prompting technique. Last, the requirements.txt -file has all the requirements needed to get the sample application up and running. -## Step 2: +# How to use this Repo: -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: +## Prerequisites: -``` -pip install virtualenv -python3.10 -m venv venv -``` +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -``` -cd venv -cd bin -source activate -cd ../../ -``` -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: +1. Access to Amazon Athena and the ability to create an Amazon Athena database and tables. -``` -pip install -r requirements.txt -``` -## Step 3: +## Steps +1. Clone the repository to your local machine. -Now that all the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `amazon_athena_bedrock_query.py` - contains connectors into your Amazon Athena database and the interaction + + * `moma_examples.yaml` - contains several samples prompts that will be used to implement a few-shot prompting technique. + + -``` -profile_name= -aws_access_key_id= -aws_secret_access_key= -region_name= -database_name= -s3_staging_dir= example -> s3://sample-bucket/ -``` +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc + ``` -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure lines 19-25 in the amazon_athena_bedrock_query.py file: +1. Create a .env file in the root folder of this POC. Within the .env file you just created you will need to configure the .env to contain: -``` -llm = Bedrock( - credentials_profile_name=os.getenv("profile_name"), - model_id="amazon.titan-text-express-v1", - endpoint_url="https://bedrock-runtime.us-east-1.amazonaws.com", - region_name="us-east-1", - verbose=True -) -``` + ```zsh + profile_name= + aws_access_key_id= + aws_secret_access_key= + region_name= + database_name= + s3_staging_dir= example -> s3://sample-bucket/ + ``` -# Step 4 -If you would like to use this repo with the sample data, you will need to upload the two sample data files found in the sample data directory as two individual tables to your Amazon Athena Database. +1. If you would like to use this repo with the sample data, you will need to upload the two sample data files found in the sample data directory as two individual tables to your Amazon Athena Database. If you preferred to use your own database/tables in your Amazon Athena database, I would highly recommend reviewing the moma_examples.yaml file in the SampleData directory to see how prompts are constructed for this sample application and spend the time creating 5 - 10 prompts that resemble your dataset more closely. -# Step 5 -At this point the application should be ready to go. To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin asking natural language questions against your Amazon Athena Database. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/requirements.txt index 074289ce..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-athena-poc/requirements.txt @@ -1,113 +1,5 @@ -aiohttp==3.9.2 -aiosignal==1.3.1 -altair==5.1.2 -annotated-types==0.6.0 -anyio==3.7.1 -async-timeout==4.0.3 -attrs==23.1.0 -backoff==2.2.1 -bcrypt==4.0.1 -blinker==1.6.3 -boto3==1.34.69 -botocore==1.34.69 -cachetools==5.3.1 -certifi==2023.7.22 -charset-normalizer==3.3.0 -click==8.1.7 -coloredlogs==15.0.1 -dataclasses-json==0.6.1 -exceptiongroup==1.1.3 -fastapi==0.109.1 -filelock==3.12.4 -flatbuffers==23.5.26 -frozenlist==1.4.0 -fsspec==2023.9.2 -gitdb==4.0.10 -GitPython==3.1.41 -grpcio==1.59.0 -h11==0.14.0 -httptools==0.6.0 -humanfriendly==10.0 -idna==3.4 -importlib-metadata==6.8.0 -importlib-resources==6.1.0 -Jinja2==3.1.3 -jmespath==1.0.1 -joblib==1.3.2 -jsonpatch==1.33 -jsonpointer==2.4 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -marshmallow==3.20.1 -mdurl==0.1.2 -monotonic==1.6 -mpmath==1.3.0 -multidict==6.0.4 -mypy-extensions==1.0.0 -networkx==3.1 -nltk==3.8.1 -numpy==1.26.0 -onnxruntime==1.17.1 -overrides==7.4.0 -packaging==23.2 -pandas==2.1.1 -Pillow==10.2.0 -pip==23.3 -posthog==3.0.2 -protobuf==4.24.4 -pulsar-client==3.4.0 -pyarrow==14.0.1 -PyAthena==3.0.9 -pydantic==2.4.2 -pydantic_core==2.10.1 -pydeck==0.8.1b0 -Pygments==2.16.1 -PyPika==0.48.9 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -PyYAML==6.0.1 -referencing==0.30.2 -regex==2023.10.3 -requests==2.31.0 -rich==13.6.0 -rpds-py==0.10.6 -s3transfer==0.10.0 -safetensors==0.4.0 -scikit-learn==1.3.1 -scipy==1.11.3 -sentence-transformers==2.2.2 -sentencepiece==0.1.99 -setuptools==68.2.0 -six==1.16.0 -smmap==5.0.1 -sniffio==1.3.0 -starlette==0.35.0 -streamlit==1.38.0 -sympy==1.12 -tenacity==8.2.3 -threadpoolctl==3.2.0 -tokenizers==0.15.2 -toml==0.10.2 -toolz==0.12.0 -torch==2.2.0 -torchvision==0.17.0 -tornado==6.3.3 -tqdm==4.66.1 -transformers==4.36.0 -typer==0.9.0 -typing_extensions==4.8.0 -typing-inspect==0.9.0 -tzdata==2023.3 -tzlocal==5.1 -urllib3==2.0.7 -uvicorn==0.23.2 -uvloop==0.17.0 -validators==0.22.0 -watchfiles==0.21.0 -websockets==11.0.3 -wheel==0.41.2 -yarl==1.9.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.projen/deps.json new file mode 100644 index 00000000..a7b559b5 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.projen/deps.json @@ -0,0 +1,39 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "langchain-community", + "type": "runtime" + }, + { + "name": "langchain-experimental", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.1", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/README.md index a0e0e3e5..9a1b5c42 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/README.md @@ -1,115 +1,101 @@ -# Amazon-Bedrock-Amazon-RDS-POC +# Amazon Bedrock & Amazon RDS POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to use natural language questions to query relational data stores, specifically Amazon RDS. This example leverages the MOMA Open Source Database: https://github.com/MuseumofModernArt/collection. -![Alt text](images/demo.gif) +![A gif of a screen recording show casing the Amazon Bedrock & Amazon RDS POC functionality](images/demo.gif) -# **Goal of this Repo:** +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to take natural language questions, and transform them into relational database queries against Amazon RDS Databases. This repo is designed to work with Amazon RDS Postgres, but can be configured to work with other database engine types. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: +When a user interacts with the POC, the flow is as follows: 1. The user makes a request, asking a natural language question based on the data in Amazon RDS to the GenAI app (app.py). -2. This natural language question is passed into Amazon Bedrock, which takes the natural language question and creates a SQL query (amazonRDS_bedrock_query.py). -3. The created SQL query is then executed against your Amazon RDS database to begin retrieving the data (amazonRDS_bedrock_query.py). -4. The data is retrieved from your Amazon RDS Database and is passed back into Amazon Bedrock, to generate a natural language answer based on the retrieved data (amazonRDS_bedrock_query.py). -5. The LLM returns a natural language response to the user through the streamlit frontend based on the retrieved data (app.py). -# How to use this Repo: +1. This natural language question is passed into Amazon Bedrock, which takes the natural language question and creates a SQL query (amazonRDS_bedrock_query.py). -## Prerequisites: +1. The created SQL query is then executed against your Amazon RDS database to begin retrieving the data (amazonRDS_bedrock_query.py). + +1. The data is retrieved from your Amazon RDS Database and is passed back into Amazon Bedrock, to generate a natural language answer based on the retrieved data (amazonRDS_bedrock_query.py). -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Amazon RDS Access and the ability to create a database. -3. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3100/). -4. Please note that this project leverages the [langchain-experimental](https://pypi.org/project/langchain-experimental/) package which has known vulnerabilities. +1. The LLM returns a natural language response to the user through the streamlit frontend based on the retrieved data (app.py). -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open it up in your favorite code editor.The file structure of this repo is broken into 4 key files, -the app.py file, the amazonRDS_bedrock_query.py file, the moma_examples.yaml file, and the requirements.txt. The app.py file houses the frontend application (streamlit app). -The amazonRDS_bedrock_query.py file contains connectors into your Amazon RDS instance and the interaction with Amazon Bedrock through LangChains SQLDatabaseChain. -The moma_examples.yaml file contains several samples prompts that will be used to implement a few-shot prompting technique. Last, the requirements.txt -file has all the requirements needed to get the sample application up and running. +# How to use this Repo: + +## Prerequisites: -## Step 2: +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.10. This can be done by running the following commands: +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -``` -pip install virtualenv -python3.10 -m venv venv -``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: +1. Access to Amazon RDS and the ability to create an Amazon RDS database and tables. -``` -cd venv -cd bin -source activate -cd ../../ -``` +1. Please note that this project leverages the [langchain-experimental](https://pypi.org/project/langchain-experimental/) package which has known vulnerabilities. -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: -``` -pip install -r requirements.txt -``` +## Steps +1. Clone the repository to your local machine. -## Step 3: + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `amazonRDS_bedrock_query.py` - contains connectors into your Amazon RDS database and the interaction + + * `moma_examples.yaml` - contains several samples prompts that will be used to implement a few-shot prompting technique. + + -Now that all the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc + ``` -``` -profile_name= -rds_username= -rds_password= -rds_endpoint= -rds_port= -rds_db_name= -``` +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! +1. Create a .env file in the root folder of this POC. Within the .env file you just created you will need to configure the .env to contain: -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure lines 19-25 in the amazonRDS_bedrock_query.py file: + ```zsh + profile_name= rds_username= rds_password= rds_endpoint= rds_port= + rds_db_name= -``` -llm = Bedrock( - credentials_profile_name=os.getenv("profile_name"), - model_id="amazon.titan-text-express-v1", - endpoint_url="https://bedrock-runtime.us-east-1.amazonaws.com", - region_name="us-east-1", - verbose=True -) -``` + ``` -# Step 4 -If you would like to use this repo with the sample data, you will need to upload the two sample data files found in the sample data directory as two individual tables to your Amazon RDS Postgres Database. +1. If you would like to use this repo with the sample data, you will need to upload the two sample data files found in the sample data directory as two individual tables to your Amazon RDS Postgres Database. If you preferred to use your own database/tables in your Amazon RDS instance, I would highly recommend reviewing the moma_examples.yaml file in the SampleData directory to see how prompts are constructed for this sample application and spend the time creating 5 - 10 prompts that resemble your dataset more closely. -# Step 5 -At this point the application should be ready to go. To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin asking natural language questions against your Amazon RDS Database. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/requirements.txt index ac47ea82..eb14cd31 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-rds-poc/requirements.txt @@ -1,121 +1,8 @@ -aiohttp==3.9.2 -aiosignal==1.3.1 -altair==5.1.2 -annotated-types==0.6.0 -anyio==3.7.1 -async-timeout==4.0.3 -attrs==23.1.0 -backoff==2.2.1 -bcrypt==4.0.1 -blinker==1.6.3 -boto3==1.34.69 -botocore==1.34.69 -cachetools==5.3.1 -certifi==2023.7.22 -charset-normalizer==3.3.0 -chroma-hnswlib==0.7.3 -chromadb==0.4.14 -click==8.1.7 -coloredlogs==15.0.1 -dataclasses-json==0.6.1 -exceptiongroup==1.1.3 -fastapi==0.109.1 -filelock==3.12.4 -flatbuffers==23.5.26 -frozenlist==1.4.0 -fsspec==2023.9.2 -gitdb==4.0.10 -GitPython==3.1.41 -grpcio==1.59.0 -h11==0.14.0 -httptools==0.6.0 -huggingface-hub==0.21.4 -humanfriendly==10.0 -idna==3.4 -importlib-metadata==6.8.0 -importlib-resources==6.1.0 -Jinja2==3.1.3 -jmespath==1.0.1 -joblib==1.3.2 -jsonpatch==1.33 -jsonpointer==2.4 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -langchain==0.1.13 -langchain-community==0.0.31 -langchain-experimental==0.0.55 -langsmith==0.1.17 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -marshmallow==3.20.1 -mdurl==0.1.2 -monotonic==1.6 -mpmath==1.3.0 -multidict==6.0.4 -mypy-extensions==1.0.0 -networkx==3.1 -nltk==3.8.1 -numpy==1.26.0 -onnxruntime==1.17.1 -overrides==7.4.0 -packaging==23.2 -pandas==2.1.1 -Pillow==10.2.0 -pip==23.3 -posthog==3.0.2 -protobuf==4.24.4 -psycopg2-binary==2.9.9 -pulsar-client==3.4.0 -pyarrow==14.0.1 -pydantic==2.4.2 -pydantic_core==2.10.1 -pydeck==0.8.1b0 -Pygments==2.16.1 -PyPika==0.48.9 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -PyYAML==6.0.1 -referencing==0.30.2 -regex==2023.10.3 -requests==2.31.0 -rich==13.6.0 -rpds-py==0.10.6 -s3transfer==0.10.0 -safetensors==0.4.0 -scikit-learn==1.3.1 -scipy==1.11.3 -sentence-transformers==2.2.2 -sentencepiece==0.1.99 -setuptools==68.2.0 -six==1.16.0 -smmap==5.0.1 -sniffio==1.3.0 -SQLAlchemy==2.0.21 -starlette==0.35.0 -streamlit==1.30.0 -sympy==1.12 -tenacity==8.2.3 -threadpoolctl==3.2.0 -tokenizers==0.15.2 -toml==0.10.2 -toolz==0.12.0 -torch==2.2.0 -torchvision==0.17.0 -tornado==6.3.3 -tqdm==4.66.1 -transformers==4.36.0 -typer==0.9.0 -typing_extensions==4.8.0 -typing-inspect==0.9.0 -tzdata==2023.3 -tzlocal==5.1 -urllib3==2.0.7 -uvicorn==0.23.2 -uvloop==0.17.0 -validators==0.22.0 -watchfiles==0.21.0 -websockets==11.0.3 -wheel==0.41.2 -yarl==1.9.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +langchain-community +langchain-experimental +langchain>=0.1.0, <0.2.0 +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.projen/deps.json new file mode 100644 index 00000000..a7b559b5 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.projen/deps.json @@ -0,0 +1,39 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "langchain-community", + "type": "runtime" + }, + { + "name": "langchain-experimental", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.1", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/README.md index 444751c4..1ece1a63 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/README.md @@ -1,115 +1,114 @@ -# Amazon-Bedrock-Amazon-Redshift-POC +# Amazon Bedrock & Amazon Redshift POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to use natural language questions to query relational data stores, specifically Amazon Redshift. This example leverages the MOMA Open Source Database: https://github.com/MuseumofModernArt/collection. -**Please Note: If you don't want to build this from scratch, Amazon Redshift now supports GenAI capabilities natively, more information on that can be found [here](https://aws.amazon.com/blogs/aws/amazon-redshift-adds-new-ai-capabilities-to-boost-efficiency-and-productivity/).** + **Please Note: If you don't want to build this from scratch, Amazon Redshift now supports GenAI capabilities natively, more information on that can be found [here](https://aws.amazon.com/blogs/aws/amazon-redshift-adds-new-ai-capabilities-to-boost-efficiency-and-productivity/).** -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock & Amazon Redshift POC functionality](images/demo.gif) -The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to take natural language questions, and transform them into relational database queries against Amazon Redshift Databases. This repo is designed to work with -Amazon Redshift Provisioned Clusters. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +## Goal of this POC +The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to take natural language questions, and transform them into relational database queries against Amazon Redshift Databases. This repo is designed to work with Amazon Redshift Provisioned Clusters. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -![Alt text](images/architecture.png "POC Architecture") +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -When a user interacts with the GenAI app, the flow is as follows: -1. The user makes a request, asking a natural language question based on the data in Amazon Redshift to the GenAI app (app.py). -2. This natural language question is passed into Amazon Bedrock, which takes the natural language question and creates a SQL query (amazon_redshift_bedrock_query.py). -3. The created SQL query is then executed against your Amazon Redshift cluster to begin retrieving the data (amazon_redshift_bedrock_query.py). -4. The data is retrieved from your Amazon Redshift cluster and is passed back into Amazon Bedrock, to generate a natural language answer based on the retrieved data (amazon_redshift_bedrock_query.py). -5. The LLM returns a natural language response to the user through the streamlit frontend based on the retrieved data (app.py). +When a user interacts with the POC, the flow is as follows: -# How to use this Repo: +1. The user makes a request, asking a natural language question based on the data in Amazon Redshift to the GenAI app (`app.py`) -## Prerequisites: +1. This natural language question is passed into Amazon Bedrock, which takes the natural language question and creates a SQL query (`amazon_redshift_bedrock_query.py`) + +1. The created SQL query is then executed against your Amazon Redshift cluster to begin retrieving the data (`amazon_redshift_bedrock_query.py`). + +1. The data is retrieved from your Amazon Redshift Database and is passed back into Amazon Bedrock, to generate a natural language answer based on the retrieved data (`amazon_redshift_bedrock_query.py`). + +1. The LLM returns a natural language response to the user through the streamlit frontend based on the retrieved data (`app.py`). -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Amazon Redshift Access and the ability to create an Amazon Redshift Provisioned cluster. -3. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3100/). -4. Please note that this project leverages the [langchain-experimental](https://pypi.org/project/langchain-experimental/) package which has known vulnerabilities. -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` +# How to use this Repo: + +## Prerequisites: + +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -After cloning the repo onto your local machine, open it up in your favorite code editor.The file structure of this repo is broken into 4 key files, -the app.py file, the amazon_redshift_bedrock_query.py file, the moma_examples.yaml file, and the requirements.txt. The app.py file houses the frontend application (streamlit app). -The amazon_redshift_bedrock_query.py file contains connectors into your Amazon Redshift cluster and the interaction with Amazon Bedrock through LangChains SQLDatabaseChain. -The moma_examples.yaml file contains several samples prompts that will be used to implement a few-shot prompting technique. Last, the requirements.txt -file has all the requirements needed to get the sample application up and running. -## Step 2: +1. Access to Amazon Redshift and the ability to create an Amazon Redshift cluster and tables. -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: +1. Please note that this project leverages the [langchain-experimental](https://pypi.org/project/langchain-experimental/) package which has known vulnerabilities. -``` -pip install virtualenv -python3.10 -m venv venv -``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: +## Steps +1. Clone the repository to your local machine. -``` -cd venv -cd bin -source activate -cd ../../ -``` + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `amazon_redshift_bedrock_query.py` - contains connectors into your Amazon Redshift database and the interaction + + * `moma_examples.yaml` - contains several samples prompts that will be used to implement a few-shot prompting technique. + + -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc + ``` -``` -pip install -r requirements.txt -``` +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -## Step 3: +1. Create a .env file in the root folder of this POC. Within the .env file you just created you will need to configure the .env to contain: -Now that all the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: + ```zsh + profile_name= redshift_host= example -> redshift-cluster-1.abcdefghijk123.us-east-1.redshift.amazonaws.com redshift_username= redshift_password= redshift_endpoint= redshift_port= + redshift_db_name= -``` -profile_name= -redshift_host= example -> redshift-cluster-1.abcdefghijk123.us-east-1.redshift.amazonaws.com -redshift_port= -redshift_database= -redshift_username= -redshift_password= -``` + ``` -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure lines 19-25 in the amazon_redshift_bedrock_query.py file: +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure lines 19-25 in the amazon_redshift_bedrock_query.py file: -``` -llm = Bedrock( + ```zsh + llm = Bedrock( credentials_profile_name=os.getenv("profile_name"), model_id="amazon.titan-text-express-v1", endpoint_url="https://bedrock-runtime.us-east-1.amazonaws.com", region_name="us-east-1", verbose=True ) -``` + ``` -# Step 4 -If you would like to use this repo with the sample data, you will need to upload the two sample data files found in the sample data directory as two individual tables to your Amazon Redshift Cluster. +1. If you would like to use this repo with the sample data, you will need to upload the two sample data files found in the sample data directory as two individual tables to your Amazon Redshift Database. -If you preferred to use your own database/tables in your Amazon Redshift Cluster, I would highly recommend reviewing the moma_examples.yaml file in the SampleData directory to see how prompts are constructed for this sample application and spend the time creating 5 - 10 prompts that resemble your dataset more closely. +If you preferred to use your own database/tables in your Amazon Redshift instance, I would highly recommend reviewing the moma_examples.yaml file in the SampleData directory to see how prompts are constructed for this sample application and spend the time creating 5 - 10 prompts that resemble your dataset more closely. -# Step 5 -At this point the application should be ready to go. To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin asking natural language questions against your Amazon Redshift Cluster. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/requirements.txt index 676df2ac..eb14cd31 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-amazon-redshift-poc/requirements.txt @@ -1,122 +1,8 @@ -aiohttp==3.9.2 -aiosignal==1.3.1 -altair==5.1.2 -annotated-types==0.6.0 -anyio==3.7.1 -async-timeout==4.0.3 -attrs==23.1.0 -backoff==2.2.1 -bcrypt==4.0.1 -blinker==1.6.3 -boto3==1.34.69 -botocore==1.34.69 -cachetools==5.3.1 -certifi==2023.7.22 -charset-normalizer==3.3.0 -chroma-hnswlib==0.7.3 -chromadb==0.4.14 -click==8.1.7 -coloredlogs==15.0.1 -dataclasses-json==0.6.1 -exceptiongroup==1.1.3 -fastapi==0.109.1 -filelock==3.12.4 -flatbuffers==23.5.26 -frozenlist==1.4.0 -fsspec==2023.9.2 -gitdb==4.0.10 -GitPython==3.1.41 -grpcio==1.59.0 -h11==0.14.0 -httptools==0.6.0 -huggingface-hub==0.21.4 -humanfriendly==10.0 -idna==3.4 -importlib-metadata==6.8.0 -importlib-resources==6.1.0 -Jinja2==3.1.3 -jmespath==1.0.1 -joblib==1.3.2 -jsonpatch==1.33 -jsonpointer==2.4 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -langchain==0.1.13 -langchain-community==0.0.31 -langchain-experimental==0.0.55 -langsmith==0.1.17 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -marshmallow==3.20.1 -mdurl==0.1.2 -monotonic==1.6 -mpmath==1.3.0 -multidict==6.0.4 -mypy-extensions==1.0.0 -networkx==3.1 -nltk==3.8.1 -numpy==1.26.0 -onnxruntime==1.17.1 -overrides==7.4.0 -packaging==23.2 -pandas==2.1.1 -Pillow==10.2.0 -pip==23.3 -posthog==3.0.2 -protobuf==4.24.4 -psycopg2-binary==2.9.9 -pulsar-client==3.4.0 -pyarrow==14.0.1 -pydantic==2.4.2 -pydantic_core==2.10.1 -pydeck==0.8.1b0 -Pygments==2.16.1 -PyPika==0.48.9 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -PyYAML==6.0.1 -referencing==0.30.2 -regex==2023.10.3 -requests==2.31.0 -rich==13.6.0 -rpds-py==0.10.6 -s3transfer==0.10.0 -safetensors==0.4.0 -scikit-learn==1.3.1 -scipy==1.11.3 -sentence-transformers==2.2.2 -sentencepiece==0.1.99 -setuptools==68.2.0 -six==1.16.0 -smmap==5.0.1 -sniffio==1.3.0 -SQLAlchemy==1.4.49 -sqlalchemy-redshift==0.8.14 -starlette==0.35.0 -streamlit==1.30.0 -sympy==1.12 -tenacity==8.2.3 -threadpoolctl==3.2.0 -tokenizers==0.15.2 -toml==0.10.2 -toolz==0.12.0 -torch==2.2.0 -torchvision==0.17.0 -tornado==6.3.3 -tqdm==4.66.1 -transformers==4.36.0 -typer==0.9.0 -typing_extensions==4.8.0 -typing-inspect==0.9.0 -tzdata==2023.3 -tzlocal==5.1 -urllib3==2.0.7 -uvicorn==0.23.2 -uvloop==0.17.0 -validators==0.22.0 -watchfiles==0.20.0 -websockets==11.0.3 -wheel==0.41.2 -yarl==1.9.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +langchain-community +langchain-experimental +langchain>=0.1.0, <0.2.0 +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.projen/deps.json new file mode 100644 index 00000000..a7b559b5 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.projen/deps.json @@ -0,0 +1,39 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "langchain-community", + "type": "runtime" + }, + { + "name": "langchain-experimental", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.1", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/README.md index 2e7abb0f..1fef0941 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/README.md @@ -1,83 +1,98 @@ -# Amazon-Bedrock-Asynchronous-Invocation-POC +# Amazon Bedrock Asynchronous Invocation POC + +## Overview of Solution + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to perform asynchronous invocations of large language models. The application is constructed with a simple streamlit frontend where users can input zero shot requests directly against the LLM of their choice, leveraging asynchronous invocations, to invoke 3 models simultaneously to reduce overall latency. -![Alt text](images/demo.gif) -# **Goal of this Repo:** -The goal of this repo is to provide users the ability to use Amazon Bedrock in an asynchronous manner allowing users to invoke multiple models at once, reducing overall latency. -This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. +![A gif of a screen recording show casing the Amazon Bedrock Asynchronous Invocation POC functionality](images/demo.gif) + + +## Goal of this POC +The goal of this repo is to provide users the ability to use Amazon Bedrock and Generative AI to perform asynchronous invocations of large language models. The application is constructed with a simple streamlit frontend where users can input zero shot requests directly against the LLM of their choice, leveraging asynchronous invocations, to invoke 3 models simultaneously to reduce overall latency. + +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') + + +When a user interacts with the POC, the flow is as follows: -The architecture and flow of the sample application will be: +1. The user makes a request, asking a natural language question based on the data in Amazon RDS to the GenAI app (app.py). + +1. This natural language question is passed into Amazon Bedrock, which takes the natural language question and creates a SQL query (amazonRDS_bedrock_query.py). + +1. The created SQL query is then executed against your Amazon RDS database to begin retrieving the data (amazonRDS_bedrock_query.py). + +1. The data is retrieved from your Amazon RDS Database and is passed back into Amazon Bedrock, to generate a natural language answer based on the retrieved data (amazonRDS_bedrock_query.py). + +1. The LLM returns a natural language response to the user through the streamlit frontend based on the retrieved data (app.py). -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: -1. The user inserts a text question into to the streamlit app. (app.py). -2. The streamlit app, takes the text and passes it into 3 different LLMs (Claude 3 - Haiku, Claude 3 - Sonnet, Claude 2.1) simultaneously through an asynchronous invocation of Amazon Bedrock. (asynchronous_invocations.py). -3. A natural language response is returned for each of the models to the end user, along with a timer demonstrating the decrease in latency caused by using asynchronous invocations.(app.py). # How to use this Repo: ## Prerequisites: -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3100/). - -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. - -``` -https://github.com/aws-samples/genai-quickstart-pocs.git -``` - -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the asynchronous_invocations.py file and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The asynchronous_invocations.py file houses the logic of the asynchronous invocation of Amazon Bedrock. -The requirements.txt file contains all necessary dependencies for this sample application to work. - -## Step 2: -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.10. This can be done by running the following commands: -``` -pip install virtualenv -python3.10 -m venv venv -``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -cd venv -cd bin -source activate -cd ../../ -``` -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: -``` -pip install -r requirements.txt -``` - -## Step 3: -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this directory within this repo. Within the .env file you just created you will need to configure the .env to contain: - -``` -profile_name= -region_name=us-east-1 -``` -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! - -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 86 in the asynchronous_invocation.py file. Currently, this application is only suited to use Anthropic models: - -```python -async def orchestrator(question, modelID1="anthropic.claude-3-sonnet-20240229-v1:0", modelID2="anthropic.claude-3-haiku-20240307-v1:0", modelID3='anthropic.claude-v2:1'): +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. + + + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `app.py` - contains the streamlit frontend and the interaction with Amazon Bedrock + + * `amazon_bedrock_query.py` - contains connectors into your Amazon Bedrock LLMs and the interaction + + + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc + ``` + +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` + +1. Create a .env file in the root folder of this POC. Within the .env file you just created you will need to configure the .env to contain: + + ```zsh + profile_name=region_name=us-east-1 + ``` + + +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 86 in the asynchronous_invocation.py file. Currently, this application is only suited to use Anthropic models: + + ```zsh + async def orchestrator(question, modelID1="anthropic.claude-3-sonnet-20240229-v1:0", modelID2="anthropic.claude-3-haiku-20240307-v1:0", modelID3='anthropic.claude-v2:1'): result = await asyncio.gather(main(question, modelID1), main(question, modelID2), main(question, modelID3)) print(result) return result -``` + ``` + + +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -``` -streamlit run app.py -``` -As soon as the application is up and running in your browser of choice you can begin leveraging asynchronous invocations of Amazon Bedrock to invoke multiple calls to LLMs simultaneously allowing you to reduce overall latency. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/requirements.txt index 50348ae0..eb14cd31 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-asynchronous-invocation-poc/requirements.txt @@ -1,59 +1,8 @@ -aioboto3==12.4.0 -aiobotocore==2.12.3 -aiohttp==3.9.5 -aioitertools==0.11.0 -aiosignal==1.3.1 -altair==5.3.0 -async-timeout==4.0.3 -asyncio==3.4.3 -attrs==23.2.0 -blinker==1.7.0 -boto3==1.34.69 -botocore==1.34.69 -cachetools==5.3.3 -certifi==2024.2.2 -charset-normalizer==3.3.2 -click==8.1.7 -frozenlist==1.4.1 -gitdb==4.0.11 -GitPython==3.1.43 -idna==3.7 -Jinja2==3.1.3 -jmespath==1.0.1 -jsonschema==4.21.1 -jsonschema-specifications==2023.12.1 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -mdurl==0.1.2 -multidict==6.0.5 -numpy==1.26.4 -packaging==24.0 -pandas==2.2.2 -pillow==10.3.0 -pip==23.2.1 -protobuf==4.25.3 -pyarrow==15.0.2 -pydeck==0.8.1b0 -Pygments==2.17.2 -python-dateutil==2.9.0.post0 -python-dotenv==1.0.1 -pytz==2024.1 -referencing==0.34.0 -requests==2.31.0 -rich==13.7.1 -rpds-py==0.18.0 -s3transfer==0.10.1 -setuptools==68.2.0 -six==1.16.0 -smmap==5.0.1 -streamlit==1.33.0 -tenacity==8.2.3 -toml==0.10.2 -toolz==0.12.1 -tornado==6.4 -typing_extensions==4.11.0 -tzdata==2024.1 -urllib3==2.2.1 -wheel==0.41.2 -wrapt==1.16.0 -yarl==1.9.4 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +langchain-community +langchain-experimental +langchain>=0.1.0, <0.2.0 +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.projen/deps.json new file mode 100644 index 00000000..a7b559b5 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.projen/deps.json @@ -0,0 +1,39 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "langchain-community", + "type": "runtime" + }, + { + "name": "langchain-experimental", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.1", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/README.md index 8c1bafb5..081196a5 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/README.md @@ -1,92 +1,91 @@ -# Amazon-Bedrock-Chat-POC +# Amazon Bedrock Chat POC -This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a ChatGPT alternative. The application is constructed with a simple streamlit frontend where users can input zero shot requests to satisfy a broad range of use cases. +## Overview of Solution -![Alt text](images/demo.gif) -# **Goal of this Repo:** -The goal of this repo is to provide users the ability to use Amazon Bedrock in a similar fashion to ChatGPT. -This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +![A gif of a screen recording show casing the Amazon Bedrock Chat POC functionality](images/demo.gif) -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: +## Goal of this POC +The goal of this repo is to provide users the ability to use Amazon Bedrock in a similar fashion to ChatGPT. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -1. The user makes a "zero-shot" request to the streamlit frontend. (app.py). -2. The application performs a semantic search of the users query against the 1200+ prompts. (prompt_finder_and_invoke_llm.py). -3. The application returns the 3 most semantically similar prompts, and creates a final prompt that contains the 3 returned prompts along with users query (few-shot prompting) (prompt_finder_and_invoke_llm.py). -4. The final prompt is passed into Amazon Bedrock to generate an answer to the users question (prompt_finder_and_invoke_llm.py). -5. The final answer is generated by Amazon Bedrock and displayed on the frontend application (app.py). +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -# How to use this Repo: -## Prerequisites: +When a user interacts with the POC, the flow is as follows: + +1. The user makes a "zero-shot" request to the streamlit frontend (`app.py`) + +1. The application returns the 3 most semantically similar prompts, and creates a final prompt that contains the 3 returned prompts along with users query (few-shot prompting) (`prompt_finder_and_invoke_llm.py`). + +1. The final prompt is passed into Amazon Bedrock to generate an answer to the users question (`prompt_finder_and_invoke_llm.py`). -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). +1. The final answer is generated by Amazon Bedrock and displayed on the frontend application (`app.py`) -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 4 key files, -the app.py file, the prompt_finder_and_invoke_llm.py file, the chat_history_prompt_generator.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The prompt_finder_and_invoke_llm.py file houses the logic of the application, including the semantic search against the prompt repository and prompt formatting logic and the Amazon Bedrock API invocations. -The chat_history_prompt_generator.py houses the logic required to preserve session state and to dynamically inject the conversation history into prompts to allow for follow-up questions and conversation summary. -The requirements.txt file contains all necessary dependencies for this sample application to work. +# How to use this Repo: + +## Prerequisites: + +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -## Step 2: +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: -``` -pip install virtualenv -python3.10 -m venv venv -``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: +## Steps +1. Clone the repository to your local machine. -``` -cd venv -cd bin -source activate -cd ../../ -``` + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `prompt_finder_and_invoke_llm.py` - houses the logic of the application, including the semantic search against the prompt repository and prompt formatting logic and the Amazon Bedrock API invocations. + + * `chat_history_prompt_generator.py` - houses the logic required to preserve session state and to dynamically inject the conversation history into prompts to allow for follow-up questions and conversation summary. + + -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-chat-poc + ``` -``` -pip install -r requirements.txt -``` +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -## Step 3: +1. Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: + ```zsh + profile_name= + ``` -``` -profile_name= -``` -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 23 in the prompt_finder_and_invoke_llm.py file to set the appropriate region: -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 23 in the prompt_finder_and_invoke_llm.py file to set the appropriate region: + ```zsh + bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') + ``` -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') -``` -Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the llm_answer_generator() function in the prompt_finder_and_invoke_llm.py to look like: +1. Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the llm_answer_generator() function in the prompt_finder_and_invoke_llm.py to look like: -```python -def llm_answer_generator(question_with_prompt): + ```zsh + def llm_answer_generator(question_with_prompt): """ This function is used to invoke Amazon Bedrock using the finalized prompt that was created by the prompt_finder(question) function. @@ -118,16 +117,15 @@ def llm_answer_generator(question_with_prompt): answer = response_body.get('completion') # returning the answer as a final result, which ultimately gets returned to the end user return answer -``` -You can then change the modelId variable to the model of your choice. + ``` -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin asking zero-shot questions and leveraging this app as you would ChatGPT. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/chat_history.txt b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/chat_history.txt new file mode 100644 index 00000000..e69de29b diff --git a/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/requirements.txt index f4168267..eb14cd31 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-chat-poc/requirements.txt @@ -1,122 +1,8 @@ -aiohttp==3.9.2 -aiosignal==1.3.1 -altair==5.1.2 -annotated-types==0.5.0 -anyio==3.7.1 -async-timeout==4.0.3 -attrs==23.1.0 -awscli==1.29.61 -backoff==2.2.1 -bcrypt==4.0.1 -blinker==1.6.2 -boto3==1.28.61 -botocore==1.31.61 -cachetools==5.3.1 -certifi==2023.7.22 -charset-normalizer==3.3.0 -chroma-hnswlib==0.7.3 -chromadb==0.4.13 -click==8.1.7 -colorama==0.4.4 -coloredlogs==15.0.1 -dataclasses-json==0.6.1 -docutils==0.16 -exceptiongroup==1.1.3 -fastapi==0.109.1 -filelock==3.12.4 -flatbuffers==23.5.26 -frozenlist==1.4.0 -fsspec==2023.9.2 -gitdb==4.0.10 -GitPython==3.1.41 -h11==0.14.0 -httptools==0.6.0 -huggingface-hub==0.17.3 -humanfriendly==10.0 -idna==3.4 -importlib-metadata==6.8.0 -importlib-resources==6.1.0 -Jinja2==3.1.3 -jmespath==1.0.1 -joblib==1.3.2 -jsonpatch==1.33 -jsonpointer==2.4 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -langchain==0.1.11 -langchain-community==0.0.31 -langsmith==0.1.17 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -marshmallow==3.20.1 -mdurl==0.1.2 -monotonic==1.6 -mpmath==1.3.0 -multidict==6.0.4 -mypy-extensions==1.0.0 -networkx==3.1 -nltk==3.8.1 -numpy==1.26.0 -onnxruntime==1.16.0 -overrides==7.4.0 -packaging==23.2 -pandas==2.1.1 -Pillow==10.2.0 -pip==23.3 -posthog==3.0.2 -protobuf==4.24.4 -pulsar-client==3.3.0 -pyarrow==14.0.1 -pyasn1==0.5.0 -pydantic==2.4.2 -pydantic_core==2.10.1 -pydeck==0.8.1b0 -Pygments==2.16.1 -PyPika==0.48.9 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -PyYAML==6.0.1 -referencing==0.30.2 -regex==2023.10.3 -requests==2.31.0 -rich==13.6.0 -rpds-py==0.10.4 -rsa==4.7.2 -s3transfer==0.7.0 -safetensors==0.4.0 -scikit-learn==1.3.1 -scipy==1.11.3 -sentencepiece==0.1.99 -sentence-transformers==2.6.1 -setuptools==65.5.1 -six==1.16.0 -smmap==5.0.1 -sniffio==1.3.0 -SQLAlchemy==2.0.21 -starlette==0.35.0 -streamlit==1.30.0 -sympy==1.12 -tenacity==8.2.3 -threadpoolctl==3.2.0 -tokenizers==0.14.1 -toml==0.10.2 -toolz==0.12.0 -torch==2.1.0 -torchvision==0.16.0 -tornado==6.3.3 -tqdm==4.66.1 -typer==0.9.0 -typing_extensions==4.8.0 -typing-inspect==0.9.0 -tzdata==2023.3 -tzlocal==5.1 -urllib3==1.26.18 -uvicorn==0.23.2 -uvloop==0.17.0 -validators==0.22.0 -watchfiles==0.20.0 -websockets==11.0.3 -wheel==0.38.4 -yarl==1.9.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +langchain-community +langchain-experimental +langchain>=0.1.0, <0.2.0 +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.projen/deps.json new file mode 100644 index 00000000..a7b559b5 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.projen/deps.json @@ -0,0 +1,39 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "langchain-community", + "type": "runtime" + }, + { + "name": "langchain-experimental", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.1", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/README.md index 0fd8ff7f..97e53c78 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/README.md @@ -1,101 +1,99 @@ -# Amazon-Bedrock-Image-Analysis-POC +# Amazon Bedrock Claude 3 Image Analysis POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Multi-Modal Generative AI models from Anthropic to implement an image analysis use case. The application is constructed with a simple streamlit frontend where users can upload a 1 page jpeg, png or PDF and get a description of the image. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Claude 3 Image Analysis POC functionality](images/demo.gif) -The goal of this repo is to provide users with the ability to analyze images with Generative AI. This can be integrated into applications like image classification, reverse image lookup, object detection and more. This repo comes iwth a basic streamlit front-end to help users stand up a proof of concept and experiment with image analysis use-cases quickly. +## Goal of this POC +The goal of this repo is to provide users with the ability to analyze images with Generative AI. This can be integrated into applications like image classification, reverse image lookup, object detection and more. This repo comes iwth a basic streamlit front-end to help users stand up a proof of concept and experiment with image analysis use-cases quickly. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: +When a user interacts with the POC, the flow is as follows: -1. The user uploads an image for bedrock model to analyze. (app.py). -2. The streamlit app, takes the image input, and invokes Amazon Bedrock to generate a description (analyze_images.py). -3. The image created by Amazon Bedrock is returned and displayed on the streamlit app (app.py). +1. The user uploads an image for bedrock model to analyze. (`app.py`). -# How to use this Repo: +1. The streamlit app, takes the image input, and invokes Amazon Bedrock to generate a description (`analyze_images.py`). -## Prerequisites: +1. The image created by Amazon Bedrock is returned and displayed on the streamlit app (`app.py`). -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` +# How to use this Repo: -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the analyze_images.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The analyze_images.py file houses the logic of the application, including the Amazon Bedrock API invocations to generate descriptions of an image. -The requirements.txt file contains all necessary dependencies for this sample application to work. +## Prerequisites: -## Step 2: +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -``` -pip install virtualenv -python3.10 -m venv venv -``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -cd venv -cd bin -source activate -cd ../../ -``` +## Steps +1. Clone the repository to your local machine. -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `analyze_images.py` - house the logic of the application, including the semantic search against the prompt repository and prompt formatting logic and the Amazon Bedrock API invocations. + + -``` -pip install -r requirements.txt -``` +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc + ``` -## Step 3: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: -``` -profile_name= -``` + ```zsh + profile_name= + ``` -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! -Depending on the region and model that you are planning to use with Amazon Bedrock (please note that only a few models can analyze images), you may need to reconfigure model paramaters in the image_analysis file. You might also choose to customize your prompts if this POC is for an industry-specific use-case analyzing a specific type of image: +1. Depending on the region and model that you are planning to use with Amazon Bedrock (please note that only a few models can analyze images), you may need to reconfigure model paramaters in the image_analysis file. You might also choose to customize your prompts if this POC is for an industry-specific use-case analyzing a specific type of image: -``` -brclient = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com',config=config) + ```zsh + brclient = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com',config=config) #model params model_id = "anthropic.claude-3-sonnet-20240229-v1:0" -``` + ``` + -You may also choose to customize the system prompt to align with a pecific use-case, or to get specific responses back about your images. +1. You may also choose to customize the system prompt to align with a pecific use-case, or to get specific responses back about your images. -``` - system_prompt = "You are an expert in image analysis and classification. The question will be contained within the tags. Before answering, think step by step in tags as you analyze every part of the image. Provide your answer within the tags. Incude a JSON structured response describing image attributes contained within the tags. Always add line breaks between each section of your response" -``` + ```zsh + system_prompt = "You are an expert in image analysis and classification. The question will be contained within the tags. Before answering, think step by step in tags as you analyze every part of the image. Provide your answer within the tags. Incude a JSON structured response describing image attributes contained within the tags. Always add line breaks between each section of your response" + ``` -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin analyzing JPEG images! diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/requirements.txt index 1cf23597..eb14cd31 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-image-analysis-poc/requirements.txt @@ -1,52 +1,8 @@ -altair==5.2.0 -attrs==23.2.0 -blinker==1.7.0 -boto3==1.34.56 -botocore==1.34.56 -cachetools==5.3.3 -certifi==2024.2.2 -charset-normalizer==3.3.2 -click==8.1.7 -gitdb==4.0.11 -GitPython==3.1.42 -idna==3.6 -importlib-metadata==7.0.1 -Jinja2==3.1.3 -jmespath==1.0.1 -jsonschema==4.21.1 -jsonschema-specifications==2023.12.1 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -mdurl==0.1.2 -numpy==1.26.4 -packaging==23.2 -pandas==2.2.1 -pillow==10.2.0 -pip==23.3 -protobuf==4.25.3 -pyarrow==15.0.0 -pydeck==0.8.1b0 -Pygments==2.17.2 -python-dateutil==2.9.0.post0 -python-dotenv==1.0.1 -pytz==2024.1 -referencing==0.33.0 -requests==2.31.0 -rich==13.7.1 -rpds-py==0.18.0 -s3transfer==0.10.0 -setuptools==68.2.0 -six==1.16.0 -smmap==5.0.1 -streamlit==1.31.1 -tenacity==8.2.3 -toml==0.10.2 -toolz==0.12.1 -tornado==6.4 -typing_extensions==4.10.0 -tzdata==2024.1 -tzlocal==5.2 -urllib3==1.26.18 -validators==0.22.0 -wheel==0.41.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +langchain-community +langchain-experimental +langchain>=0.1.0, <0.2.0 +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.projen/deps.json new file mode 100644 index 00000000..f66bbe38 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.projen/deps.json @@ -0,0 +1,30 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "pypdf", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/README.md index ac4cdefe..743e43d9 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/README.md @@ -1,102 +1,91 @@ -# Amazon-Bedrock-Claude3-Long-Form-Output-POC +# Amazon Bedrock Claude 3 Long Form Output POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to translate text from a source to target language. -![Alt text](images/demo.gif) +![A gif of a screen recording show casing the Amazon Bedrock Claude 3 Long Form Output POC functionality](images/demo.gif) -# **Goal of this Repo:** +## Goal of this POC The goal of this repository is to provide users with the ability to use Amazon Bedrock to generate long form content. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the translation app they can choose from 3 interfaces (pages), the flow is as follows for each of the pages: +When a user interacts with the POC, the flow is as follows: -Text: 1. The user either selects the default prompt or inputs a prompt. -2. The application constructs the appropriate prompt and sends it to Amazon Bedrock. -3. The appliction recieves and sends the text to Amazon Bedrock for analysis of accuracy and fluency. -4. The generated text and analysis is displayed on the frontend application. - -File: -1. The user uploads a text/pdf file and selects the processing type (eg: Tranlsation). -2. The application constructs the appropriate prompt for the processing and sends it to Amazon Bedrock. -3. The generated text from the document is displayed on the frontend application. -# How to use this Repo: +1. The application constructs the appropriate prompt and sends it to Amazon Bedrock. -## Prerequisites: +1. The appliction recieves and sends the text to Amazon Bedrock for analysis of accuracy and fluency. -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3100/). +1. The generated text and analysis is displayed on the frontend application. -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open it up in your favorite code editor.The file structure of this repo is broken into 5 key files, -the Text.py file, the amazon_bedrock_trnaslation.py file, the Chat.py file, the File.py file, and the requirements.txt file. The Text.py, Chat.py, and File.py files house the frontend application (streamlit app) for their corresponding interface. -The amazon_bedrock_translation.py file contains methods which govern the interaction with Amazon Bedrock. -Last, the requirements.txt -file has all the requirements needed to get the sample application up and running. +# How to use this Repo: -## Step 2: +## Prerequisites: -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -``` -pip install virtualenv -python3.10 -m venv venv -``` +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -cd venv -cd bin -source activate -cd ../../ -``` -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: +## Steps +1. Clone the repository to your local machine. -``` -pip install -r requirements.txt -``` + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `BedrockProcessor.py` - The logic for interacting with the Amazon Bedrock service. + + -## Step 3: +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc + ``` -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -``` -profile_name= -``` +1. Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! + ```zsh + profile_name= + ``` -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 23 in the prompt_finder_and_invoke_llm.py file to set the appropriate region: -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') -``` +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 23 in the prompt_finder_and_invoke_llm.py file to set the appropriate region: -Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the modelId variable to the model of your choice and refer to the Bedrock console for the response format + ```zsh + bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') + ``` -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -Once the application is up and running in your browser, you can begin translating text, chats, or files. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/requirements.txt index de720693..7c3195f2 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-long-form-output-poc/requirements.txt @@ -1,5 +1,6 @@ -awscli==1.33.19 -boto3==1.34.137 -botocore==1.34.137 -pypdf==3.17.3 -streamlit==1.36.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +pypdf +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.projen/deps.json new file mode 100644 index 00000000..b9b43281 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.projen/deps.json @@ -0,0 +1,30 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "pillow", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/README.md index 10fc50e7..9f309db8 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/README.md @@ -1,87 +1,86 @@ -# Amazon-Bedrock-Claude3-Multi-Modal-Sample +# Amazon Bedrock Claude 3 Multi-Modal POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Anthropic Claude 3 to satisfy multi-modal use cases. The application is constructed with a simple streamlit frontend where users can input zero shot requests to satisfy a broad range of use cases, including image to text multi-modal style use cases. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Claude 3 Multi-Modal POC functionality](images/demo.gif) -The goal of this repo is to provide users the ability to use Amazon Bedrock (specifically Claude3) and generative AI to leverage its multi-modal capabilities, allowing users to insert text questions, images, or both to get a comprehensive description/or answer based on the image and/or question that was passed in. -This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +## Goal of this POC +The goal of this repo is to provide users the ability to use Amazon Bedrock (specifically Claude3) and generative AI to leverage its multi-modal capabilities, allowing users to insert text questions, images, or both to get a comprehensive description/or answer based on the image and/or question that was passed in. + This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -![Alt text](images/architecture.png "POC Architecture") +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -When a user interacts with the GenAI app, the flow is as follows: -1. (1a) The user uploads an image file to the streamlit app, with or without a text question. (app.py). (1b) The user inserts a text question into to the streamlit app, with or without an image. (app.py). -2. The streamlit app, takes the image file and/or text and saves it. The image and/or text is passed into Amazon Bedrock (Anthropic Claude 3). (llm_multi_modal_invoke.py). -3. A natural language response is returned to the end user, either describing the image, answering a question about the image, or answering a question in general. (app.py). +When a user interacts with the POC, the flow is as follows: -# How to use this Repo: +1. The user uploads an image file to the streamlit app, with or without a text question. (`app.py`) -## Prerequisites: +1. The user inserts a text question into to the streamlit app, with or without an image. (`app.py`) + +1. The streamlit app, takes the image file and/or text and saves it. The image and/or text is passed into Amazon Bedrock (Anthropic Claude 3). (`llm_multi_modal_invoke.py`) -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). +1. A natural language response is returned to the end user, either describing the image, answering a question about the image, or answering a question in general. (`app.py`) -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the llm_multi_modal_invoke.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The llm_multi_modal_invoke.py file houses the logic of the application, including the image encoding and Amazon Bedrock API invocations. -The requirements.txt file contains all necessary dependencies for this sample application to work. +# How to use this Repo: + +## Prerequisites: -## Step 2: +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -``` -pip install virtualenv -python3.10 -m venv venv -``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -cd venv -cd bin -source activate -cd ../../ -``` +## Steps +1. Clone the repository to your local machine. -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `llm_multi_modal_invoke.py` - Houses the logic of the application, including the image encoding and Amazon Bedrock API invocations + + -``` -pip install -r requirements.txt -``` +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc + ``` -## Step 3: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: -``` -profile_name= + ```zsh + profile_name= save_folder= -``` - -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! + ``` -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin uploading images and or text questions and generating natural language responses detailing the images or the specific questions that were asked. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/requirements.txt index 361b73e1..0f4c6dff 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-multi-modal-poc/requirements.txt @@ -1,52 +1,6 @@ -altair==5.2.0 -attrs==23.2.0 -blinker==1.7.0 -boto3==1.34.56 -botocore==1.34.56 -cachetools==5.3.3 -certifi==2024.2.2 -charset-normalizer==3.3.2 -click==8.1.7 -gitdb==4.0.11 -GitPython==3.1.42 -idna==3.6 -importlib-metadata==7.0.1 -Jinja2==3.1.4 -jmespath==1.0.1 -jsonschema==4.21.1 -jsonschema-specifications==2023.12.1 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -mdurl==0.1.2 -numpy==1.26.4 -packaging==23.2 -pandas==2.2.1 -pillow==10.2.0 -pip==23.3 -protobuf==4.25.3 -pyarrow==15.0.0 -pydeck==0.8.1b0 -Pygments==2.17.2 -python-dateutil==2.9.0.post0 -python-dotenv==1.0.1 -pytz==2024.1 -referencing==0.33.0 -requests==2.31.0 -rich==13.7.1 -rpds-py==0.18.0 -s3transfer==0.10.0 -setuptools==68.2.0 -six==1.16.0 -smmap==5.0.1 -streamlit==1.31.1 -tenacity==8.2.3 -toml==0.10.2 -toolz==0.12.1 -tornado==6.4 -typing_extensions==4.10.0 -tzdata==2024.1 -tzlocal==5.2 -urllib3==1.26.18 -validators==0.22.0 -wheel==0.41.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +pillow +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/README.md index f9845231..d4bd58eb 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/README.md @@ -1,82 +1,49 @@ -# Amazon-Bedrock-Claude3-Streaming-Response-POC -This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement streaming responses. The application is constructed with a simple streamlit frontend where users can input zero shot requests directly against the LLM of their choice, leveraging a streaming response technique. +# Amazon Bedrock Claude 3 Streaming Response POC -![Alt text](images/demo.gif) -# **Goal of this Repo:** -The goal of this repo is to provide users the ability to use Amazon Bedrock leveraging its streaming response capabilities. -This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. +## Overview of Solution -The architecture and flow of the sample application will be: +This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement streaming responses. The application is constructed with a simple streamlit frontend where users can input zero shot requests directly against the LLM of their choice, leveraging a streaming response technique. -![Alt text](images/architecture.png "POC Architecture") +![A gif of a screen recording show casing the Amazon Bedrock Claude 3 Streaming Response POC functionality](images/demo.gif) -When a user interacts with the GenAI app, the flow is as follows: -1. The user inserts a text question into to the streamlit app. (app.py). -2. The streamlit app, takes the text and passes it into Amazon Bedrock. (invoke_llm_with_streaming.py). -3. A natural language response is streamed to the end user, answering a question in general. (app.py). # How to use this Repo: ## Prerequisites: -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). - -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. - -``` -https://github.com/aws-samples/genai-quickstart-pocs.git -``` - -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the invoke_llm_with_streaming.py file and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The invoke_llm_with_streaming.py file houses the invocation of Amazon Bedrock with a streaming response, and the basic prompt formatting logic. -The requirements.txt file contains all necessary dependencies for this sample application to work. - -## Step 2: -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: -``` -pip install virtualenv -python3.10 -m venv venv -``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -cd venv -cd bin -source activate -cd ../../ -``` -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: -``` -pip install -r requirements.txt -``` - -## Step 3: -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: - -``` -profile_name= -``` -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! - -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 15 in the invoke_llm_with_streaming.py file to set the region or line 51 to change to another Claude 3 model such as Haiku: - -```python -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') - -response = bedrock.invoke_model_with_response_stream(body=json_prompt, modelId="anthropic.claude-3-sonnet-20240229-v1:0", - accept="application/json", contentType="application/json") -``` - -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: - -``` -streamlit run app.py -``` -As soon as the application is up and running in your browser of choice you can begin asking zero-shot questions and leveraging Amazon Bedrock's streaming capabilities. +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. + + + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc + ``` + +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` + +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. + +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) + diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/requirements.txt index 1cfb377a..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-claude3-streaming-response-poc/requirements.txt @@ -1,52 +1,5 @@ -altair==5.2.0 -attrs==23.2.0 -blinker==1.7.0 -boto3==1.34.46 -botocore==1.34.46 -cachetools==5.3.2 -certifi==2024.2.2 -charset-normalizer==3.3.2 -click==8.1.7 -gitdb==4.0.11 -GitPython==3.1.42 -idna==3.6 -importlib-metadata==7.0.1 -Jinja2==3.1.3 -jmespath==1.0.1 -jsonschema==4.21.1 -jsonschema-specifications==2023.12.1 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -mdurl==0.1.2 -numpy==1.26.4 -packaging==23.2 -pandas==2.2.0 -pillow==10.2.0 -pip==23.3 -protobuf==4.25.3 -pyarrow==15.0.0 -pydeck==0.8.1b0 -Pygments==2.17.2 -python-dateutil==2.8.2 -python-dotenv==1.0.1 -pytz==2024.1 -referencing==0.33.0 -requests==2.31.0 -rich==13.7.0 -rpds-py==0.18.0 -s3transfer==0.10.0 -setuptools==68.2.0 -six==1.16.0 -smmap==5.0.1 -streamlit==1.31.1 -tenacity==8.2.3 -toml==0.10.2 -toolz==0.12.1 -tornado==6.4 -typing_extensions==4.9.0 -tzdata==2024.1 -tzlocal==5.2 -urllib3==1.26.18 -validators==0.22.0 -wheel==0.41.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/README.md index 71b65806..44ff4a14 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/README.md @@ -1,84 +1,92 @@ -# Amazon-Bedrock-Converse-API-POC +# Amazon Bedrock Converse API POC + +## Overview of Solution This is sample code demonstrating the use of the Amazon Bedrock Converse API to help with conversation oriented use cases that require context preservation. The application is constructed with a simple streamlit frontend where users can input zero shot requests to Claude 3, with the Amazon Bedrock Converse API in place to allow users to ask context aware questions. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Converse API POC functionality](images/demo.gif) + + +## Goal of this POC +The goal of this repo is to provide users the ability to use Amazon Bedrock leveraging its streaming response capabilities. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. + +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -The goal of this repo is to provide users the ability to use the Amazon Bedrock Converse API to demonstrate its ability to facilitate conversational GenAI use cases that require context awareness. -This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +When a user interacts with the POC, the flow is as follows: + +1. The user inserts a text question into to the streamlit app. (`app.py`) + +1. The streamlit app, takes the text and passes it into Amazon Bedrock. (`invoke_llm_with_streaming.py`) + +1. A natural language response is streamed to the end user, answering a question in general. (`app.py`) -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: -1. The user inserts a text question into to the streamlit app. (app.py). -2. The streamlit app, takes the text inserted by the user and is passed into an Amazon Bedrock Model using the Converse API. The users question is answered, and both the question and answer are stored. (invoke_model_conversation_api.py). -3. The answer to the user's question is returned to the front-end application, and allows users to ask follow up questions as the Converse API help preserve context throughout the users conversation (app.py). # How to use this Repo: ## Prerequisites: -1. Amazon Bedrock Access and CLI Credentials. -2. Create an Amazon Bedrock Guardrail, information on how to do that can be found [here](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-create.html) -3. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3100/). -so -## Step 1: - -The first step of utilizing this repo is performing a git clone of the repository. +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the invoke_model_conversation_api.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). The -invoke_model_conversation_api.py file houses the logic of the application, including the Amazon Bedrock Converse API invocation. -The requirements.txt file contains all necessary dependencies for this sample application to work. -## Step 2: -Set up a python virtual environment in the root of this specific POCs directory and ensure that you are using Python 3.10. This can be done by running the following commands: +## Steps +1. Clone the repository to your local machine. -``` -pip install virtualenv -python3.10 -m venv venv -``` + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `invoke_llm_with_streaming.py` - Houses the invocation of Amazon Bedrock with a streaming response, and the basic prompt formatting logic. + + -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc + ``` -``` -source venv/bin/activate -``` +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this specific POCs directory in your terminal: +1. Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: -``` -pip install -r requirements.txt -``` + ```zsh + profile_name= + ``` -## Step 3: -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 15 in the invoke_llm_with_streaming.py file to set the region or line 51 to change to another Claude 3 model such as Haiku: -``` -profile_name= -``` + ```zsh + bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! +response = bedrock.invoke_model_with_response_stream(body=json_prompt, modelId="anthropic.claude-3-sonnet-20240229-v1:0", + accept="application/json", contentType="application/json") + ``` -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin asking text questions and generating natural language responses having the Amazon Bedrock Converse API manage conversation history and context awareness. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/requirements.txt index e79af2c6..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-api-poc/requirements.txt @@ -1,4 +1,5 @@ -boto3==1.34.125 -python-dotenv==1.0.1 -streamlit==1.35.0 - +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/README.md index 6eaf0e72..0e52133c 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/README.md @@ -1,84 +1,85 @@ -# Amazon-Bedrock-ConverseStream-API-POC +# Amazon Bedrock Converse Stream API POC + +## Overview of Solution This is sample code demonstrating the use of the Amazon Bedrock ConverseStream API to help with conversation oriented use cases that require context preservation. The application is constructed with a simple streamlit frontend where users can input zero shot requests to Claude 3, with the Amazon Bedrock ConverseConverseStream API in place to allow users to ask context aware questions and stream the response back. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Converse Stream API POC functionality](images/demo.gif) -The goal of this repo is to provide users the ability to use the Amazon Bedrock ConverseStream API to demonstrate its ability to facilitate conversational GenAI use cases that require context awareness and streaming responses. -This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +## Goal of this POC +The goal of this repo is to provide users the ability to use the Amazon Bedrock ConverseStream API to demonstrate its ability to facilitate conversational GenAI use cases that require context awareness and streaming responses. + This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -![Alt text](images/architecture.png "POC Architecture") +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -When a user interacts with the GenAI app, the flow is as follows: -1. The user inserts a text question into to the streamlit app. (app.py). -2. The streamlit app, takes the text inserted by the user and is passed into an Amazon Bedrock Model using the ConverseStream API. The user's question is answered, and both the question and answer are stored. (invoke_model_converse_stream_api.py). -3. The answer to the user's question is streamed back to the front-end application, and allows users to ask follow up questions as the ConverseStream API help preserve context throughout the users conversation (app.py). +When a user interacts with the POC, the flow is as follows: -# How to use this Repo: +1. The user inserts a text question into to the streamlit app. (`app.py`) -## Prerequisites: +1. The streamlit app, takes the text inserted by the user and is passed into an Amazon Bedrock Model using the Converse API. The users question is answered, and both the question and answer are stored. (`invoke_model_conversation_api.py`) -1. Amazon Bedrock Access and CLI Credentials. -2. Create an Amazon Bedrock Guardrail, information on how to do that can be found [here](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-create.html) -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3100/). +1. The answer to the user's question is returned to the front-end application, and allows users to ask follow up questions as the Converse API help preserve context throughout the users conversation (`app.py`) -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the invoke_model_conversation_api.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). The -invoke_model_conversation_api.py file houses the logic of the application, including the Amazon Bedrock Converse API invocation. -The requirements.txt file contains all necessary dependencies for this sample application to work. +# How to use this Repo: + +## Prerequisites: -## Step 2: +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -Set up a python virtual environment in the root of this specific POCs directory and ensure that you are using Python 3.10. This can be done by running the following commands: +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -``` -pip install virtualenv -python3.10 -m venv venv -``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: +1. Create an Amazon Bedrock Guardrail, information on how to do that can be found [here](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-create.html) -``` -source venv/bin/activate -``` -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this specific POCs directory in your terminal: +## Steps +1. Clone the repository to your local machine. -``` -pip install -r requirements.txt -``` + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `invoke_model_converse_stream_api.py` - Houses the logic of the application, including the Amazon Bedrock Converse API invocation. + + -## Step 3: +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc + ``` -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -``` -profile_name= -``` +1. create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! + ```zsh + profile_name= + ``` -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin asking text questions and generating natural language responses having the Amazon Bedrock Converse API manage conversation history and context awareness. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/requirements.txt index 2fcdabb2..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-converse-stream-api-poc/requirements.txt @@ -1,3 +1,5 @@ -boto3==1.34.125 -python-dotenv==1.0.1 -streamlit==1.35.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.projen/deps.json new file mode 100644 index 00000000..aeb2bfb9 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.projen/deps.json @@ -0,0 +1,30 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "pandas", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/README.md index 04bedb11..c427ea20 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/README.md @@ -1,103 +1,101 @@ -# Amazon-Bedrock-CSV-Chatbot-POC +# Amazon Bedrock CSV Chatbot POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a chatbot is able to converse with the user based on CSV data provided by the user. The application is constructed with a simple streamlit frontend where users can upload large CSV files and get them analyzed or start chatbot interactions. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock CSV Chatbot POC functionality](images/demo.gif) + + +## Goal of this POC +The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to answer questions a user might have on the CSV data provided. -The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to answer questions a user might have on the CSV data provided. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: +When a user interacts with the POC, the flow is as follows: -1. The user uploads a CSV file to the streamlit app. (app.py). -2. The streamlit app, takes the CSV file and chunks the document efficient data processing(csv_data_insights.py). -3. Once the data is passed into Amazon Bedrock and the user asks the chatbot a question, it creates a response to the user's question (csv_data_insights.py). -4. After the response is generated, it is presented on the streamlit app (app.py). +1. The user uploads a CSV file to the streamlit app. (`app.py`) -# How to use this Repo: +1. The streamlit app, takes the CSV file and chunks the document efficient data processing(`csv_data_insights.py`) -## Prerequisites: +1. Once the data is passed into Amazon Bedrock and the user asks the chatbot a question, it creates a response to the user's question (`csv_data_insights.py`). -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). +1. After the response is generated, it is presented on the streamlit app (`app.py`) -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the csv_data_insights.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The csv_data_insights.py file houses the logic of the application and Amazon Bedrock API invocations. -The requirements.txt file contains all necessary dependencies for this sample application to work. +# How to use this Repo: -## Step 2: +## Prerequisites: -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -``` -pip install virtualenv -python3.10 -m venv venv -``` +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -cd venv -cd bin -source activate -cd ../../ -``` -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: +## Steps +1. Clone the repository to your local machine. -``` -pip install -r requirements.txt -``` + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `csv_data_insights.py` - Houses the logic of the application and Amazon Bedrock API invocations. + + -## Step 3: +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc + ``` -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -``` -profile_name= -save_folder= -``` +1. reate a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain -Please ensure that your AWS CLI Profile has access to Amazon Bedrock. + ```zsh + profile_name= + save_folder= + ``` -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 10 in the csv_data_insights.py file to set your region: -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock.us-east-1.amazonaws.com') +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 10 in the `csv_data_insights.py` file to set your region: -``` -Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the line 143 in the csv_data_insights.py file to look like: + ```zsh + bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock.us-east-1.amazonaws.com') + ``` -```python - response = bedrock.invoke_model(body=json_prompt, modelId="anthropic.claude-3-sonnet-20240229-v1:0", accept="application/json", contentType="application/json") -``` +1. Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the line 143 in the `csv_data_insights.py` file to look like: -You can then change the modelId to the model of your choice. + ```zsh + response = bedrock.invoke_model(body=json_prompt, modelId="anthropic.claude-3-sonnet-20240229-v1:0", accept="application/json", contentType="application/json") + ``` -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin uploading CSV documents and asking questions. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/requirements.txt index cb662a53..a6cf9e46 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-csv-chatbot-poc/requirements.txt @@ -1,83 +1,6 @@ -aiohttp==3.9.2 -aiosignal==1.3.1 -altair==5.1.1 -annotated-types==0.5.0 -anyio==3.7.1 -async-timeout==4.0.3 -attrs==23.1.0 -blinker==1.6.2 -boto3==1.28.59 -botocore==1.31.59 -cachetools==5.3.1 -certifi==2023.7.22 -charset-normalizer==3.3.0 -click==8.1.7 -dataclasses-json==0.6.1 -exceptiongroup==1.1.3 -filelock==3.12.4 -frozenlist==1.4.0 -fsspec==2023.9.2 -gitdb==4.0.10 -GitPython==3.1.41 -huggingface-hub==0.17.3 -idna==3.4 -importlib-metadata==6.8.0 -Jinja2==3.1.3 -jmespath==1.0.1 -jsonpatch==1.33 -jsonpointer==2.4 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -langchain==0.1.11 -langsmith==0.1.17 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -marshmallow==3.20.1 -mdurl==0.1.2 -multidict==6.0.4 -mypy-extensions==1.0.0 -numpy==1.26.0 -openai==0.28.1 -packaging==23.2 -pandas==2.1.1 -Pillow==10.2.0 -pip==23.3 -protobuf==4.24.3 -pyarrow==14.0.1 -pydantic==2.4.2 -pydantic_core==2.10.1 -pydeck==0.8.1b0 -Pygments==2.16.1 -pypdf==3.17.0 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -PyYAML==6.0.1 -referencing==0.30.2 -regex==2023.8.8 -requests==2.31.0 -rich==13.6.0 -rpds-py==0.10.3 -s3transfer==0.7.0 -safetensors==0.3.3 -setuptools==65.5.1 -six==1.16.0 -smmap==5.0.1 -sniffio==1.3.0 -SQLAlchemy==2.0.21 -streamlit==1.30.0 -tenacity==8.2.3 -tokenizers==0.13.3 -toml==0.10.2 -toolz==0.12.0 -tornado==6.3.3 -tqdm==4.66.1 -typing_extensions==4.8.0 -typing-inspect==0.9.0 -tzdata==2023.3 -tzlocal==5.0.1 -urllib3==1.26.18 -validators==0.22.0 -wheel==0.38.4 -yarl==1.9.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +pandas +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.projen/deps.json new file mode 100644 index 00000000..1b5f6b7e --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.projen/deps.json @@ -0,0 +1,43 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "langchain-community", + "type": "runtime" + }, + { + "name": "langchain-experimental", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.1", + "type": "runtime" + }, + { + "name": "pypdf", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/README.md index 00d9178f..bf9fe7d6 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/README.md @@ -1,125 +1,91 @@ -# Amazon-Bedrock-Document-Comparison-POC +# Amazon Bedrock Document Comparison POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a document comparison use case. The application is constructed with a simple streamlit frontend where users can upload 2 versions of a document and get all changes between documents listed. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Document Comparison POC functionality](images/demo.gif) + +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to perform document comparison between two uploaded PDFs. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') + + +When a user interacts with the POC, the flow is as follows: + +1. The user uploads two PDF files to the streamlit app. (`app.py`) + +1. The streamlit app, takes the two PDF documents, saves it, and formats it into a prompt with semantically similar examples (`doc_comparer.py`) + +1. The finalized few shot prompt containing both uploaded documents is passed into Amazon Bedrock, which generates a list of all differences between the two uploaded documents and returns the final list to the front end (`doc_comparer.py`) -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: -1. The user uploads two PDF files to the streamlit app. (app.py). -2. The streamlit app, takes the two PDF documents, saves it, and formats it into a prompt with semantically similar examples (doc_comparer.py). -3. The finalized few shot prompt containing both uploaded documents is passed into Amazon Bedrock, which generates a list of all differences between the two uploaded documents and returns the final list to the front end (doc_comparer.py). # How to use this Repo: ## Prerequisites: -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). - -## Step 1: - -The first step of utilizing this repo is performing a git clone of the repository. - -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` - -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the doc_comparer.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The doc_comparer.py file houses the logic of the application, including the prompt formatting logic and Amazon Bedrock API invocations. -The requirements.txt file contains all necessary dependencies for this sample application to work. - -## Step 2: - -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: - -``` -pip install virtualenv -python3.10 -m venv venv -``` - -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: - -``` -cd venv -cd bin -source activate -cd ../../ -``` - -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: - -``` -pip install -r requirements.txt -``` - -## Step 3: - -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: - -``` -profile_name= -save_folder= -``` - -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! - -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 20 in the doc_comparer.py file to set the appropriate region: - -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock.us-east-1.amazonaws.com') -``` -Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the llm_compare() function in the doc_comparer.py to look like: -```python -def llm_compare(prompt_data) -> str: - """ - This function uses a large language model to create a list of differences between each uploaded document. - :param prompt_data: This is the final prompt that contains semantically similar prompts, along with the two documents the user is asking to compare. - :return: A string containing a list of the differences between the two PDF documents the user uploaded. - """ - # setting the key parameters to invoke Amazon Bedrock - body = json.dumps({"prompt": prompt_data, - "max_tokens_to_sample": 8191, - "temperature": 0, - "top_k": 250, - "top_p": 0.5, - "stop_sequences": [] - }) - # the specific Amazon Bedrock model we are using - modelId = 'anthropic.claude-v2' - # type of data that should be expected upon invocation - accept = 'application/json' - contentType = 'application/json' - # the invocation of bedrock, with all the parameters you have configured - response = bedrock.invoke_model(body=body, - modelId=modelId, - accept=accept, - contentType=contentType) - # gathering the response from bedrock, and parsing to get specifically the answer - response_body = json.loads(response.get('body').read()) - answer = response_body.get('completion') - # returning the final list of differences between uploaded documents - return answer -``` -You can then change the modelId variable to the model of your choice. -## Step 4: - -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: - -``` -streamlit run app.py -``` - -As soon as the application is up and running in your browser of choice you can begin uploading PDF documents and perform document comparison. +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. + + + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `doc_comparer.py` - Houses the logic of the application, including the prompt formatting logic and Amazon Bedrock API invocations. + + + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc + ``` + +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` + +1. reate a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: + + ```zsh + profile_name= + save_folder= + ``` + + +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 20 in the doc_comparer.py file to set the appropriate region: + + ```zsh + bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock.us-east-1.amazonaws.com') + ``` + + +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. + +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) + diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/requirements.txt index b4b152f5..7887ad52 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-comparison-poc/requirements.txt @@ -1,125 +1,9 @@ -aiohttp==3.9.2 -aiosignal==1.3.1 -altair==5.1.2 -annotated-types==0.5.0 -anyio==3.7.1 -async-timeout==4.0.3 -attrs==23.1.0 -awscli==1.29.61 -backoff==2.2.1 -bcrypt==4.0.1 -blinker==1.6.2 -boto3==1.28.61 -botocore==1.31.61 -cachetools==5.3.1 -certifi==2023.7.22 -charset-normalizer==3.3.0 -chroma-hnswlib==0.7.3 -chromadb==0.4.13 -click==8.1.7 -colorama==0.4.4 -coloredlogs==15.0.1 -cryptography==42.0.5 -dataclasses-json==0.6.1 -docutils==0.16 -exceptiongroup==1.1.3 -fastapi==0.109.1 -filelock==3.12.4 -flatbuffers==23.5.26 -frozenlist==1.4.0 -fsspec==2023.9.2 -gitdb==4.0.10 -GitPython==3.1.41 -h11==0.14.0 -httptools==0.6.0 -huggingface-hub==0.21.4 -humanfriendly==10.0 -idna==3.4 -importlib-metadata==6.8.0 -importlib-resources==6.1.0 -Jinja2==3.1.3 -jmespath==1.0.1 -joblib==1.3.2 -jsonpatch==1.33 -jsonpointer==2.4 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -langchain==0.1.11 -langchain-community==0.0.31 -langsmith==0.1.17 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -marshmallow==3.20.1 -mdurl==0.1.2 -monotonic==1.6 -mpmath==1.3.0 -multidict==6.0.4 -mypy-extensions==1.0.0 -networkx==3.1 -nltk==3.8.1 -numpy==1.26.0 -onnxruntime==1.17.0 -overrides==7.4.0 -packaging==23.2 -pandas==2.1.1 -Pillow==10.2.0 -pip==23.3 -posthog==3.0.2 -protobuf==4.24.4 -pulsar-client==3.4.0 -pyarrow==14.0.1 -pyasn1==0.5.0 -pydantic==2.4.2 -pydantic_core==2.10.1 -pydeck==0.8.1b0 -Pygments==2.16.1 -pypdf==3.17.0 -PyPika==0.48.9 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -PyYAML==6.0.1 -referencing==0.30.2 -regex==2023.10.3 -requests==2.31.0 -rich==13.6.0 -rpds-py==0.10.4 -rsa==4.7.2 -s3transfer==0.7.0 -safetensors==0.4.0 -scikit-learn==1.3.1 -scipy==1.11.3 -sentence-transformers==2.2.2 -sentencepiece==0.1.99 -setuptools==65.5.1 -six==1.16.0 -smmap==5.0.1 -sniffio==1.3.0 -SQLAlchemy==2.0.21 -starlette==0.35.0 -streamlit==1.30.0 -sympy==1.12 -tenacity==8.2.3 -threadpoolctl==3.2.0 -tokenizers==0.15.2 -toml==0.10.2 -toolz==0.12.0 -torch==2.2.0 -torchvision==0.17.0 -tornado==6.3.3 -tqdm==4.66.1 -transformers==4.36.0 -typer==0.9.0 -typing_extensions==4.8.0 -typing-inspect==0.9.0 -tzdata==2023.3 -tzlocal==5.1 -urllib3==1.26.18 -uvicorn==0.23.2 -uvloop==0.17.0 -validators==0.22.0 -watchfiles==0.20.0 -websockets==11.0.3 -wheel==0.38.4 -yarl==1.9.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +langchain-community +langchain-experimental +langchain>=0.1.0, <0.2.0 +pypdf +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/README.md index ddc67b8a..22d582dd 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/README.md @@ -1,216 +1,88 @@ -# Amazon-Bedrock-Document-Generator +# Aamazon Bedrock Document Generator POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a document generation use case. The application is constructed with a simple streamlit frontend where users can provide details and create a document in the exact format that the you specify. -![Alt text](images/demo.gif) +![A gif of a screen recording show casing the Aamazon Bedrock Document Generator POC functionality](images/demo.gif) -# **Goal of this Repo:** +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to perform document generation based on a document template and details inputted by the user. + This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') + + +When a user interacts with the POC, the flow is as follows: + +1. The user inserts document details that they would like included in the generated document within the streamlit app. (`app.py`) + +1. The streamlit app, takes the document details, and invokes Amazon Bedrock to generate sample document that matches the document structure stated in the prompt containing the inserted document details (`doc_generator.py`) + +1. Amazon Bedrock generates a first draft of the sample document and presents it to the frontend (`app.py`) + +1. The user inserts refinement details highlighting areas where they would like to add refinements to the previously generated document (`app.py`) + +1. The streamlit app takes the refinement details, passes it to Amazon Bedrock along with the document prompt, and the original draft of the document to begin creating the refined version (`doc_generator.py`) + +1. Amazon Bedrock is used to generate the refined version of the document based on the user defined refinements and presents it on the frontend (`app.py`) -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: -1. The user inserts document details that they would like included in the generated document within the streamlit app. (app.py). -2. The streamlit app, takes the document details, and invokes Amazon Bedrock to generate sample document that matches the document structure stated in the prompt containing the inserted document details (doc_generator.py). -3. Amazon Bedrock generates a first draft of the sample document and presents it to the frontend (app.py). -4. The user inserts refinement details highlighting areas where they would like to add refinements to the previously generated document (app.py). -5. The streamlit app takes the refinement details, passes it to Amazon Bedrock along with the document prompt, and the original draft of the document to begin creating the refined version (doc_generator.py). -6. Amazon Bedrock is used to generate the refined version of the document based on the user defined refinements and presents it on the frontend (app.py). # How to use this Repo: ## Prerequisites: -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. + + + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc + ``` + +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` + +1. create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: + + ```zsh + profile_name= + ``` + + +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 12 in the document_generator.py file to set the appropriate region: + + ```zsh + bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') + ``` + + +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -## Step 1: +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -The first step of utilizing this repo is performing a git clone of the repository. - -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` - -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the doc_generator.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The doc_generator.py file houses the logic of the application, including the prompt formatting logic and Amazon Bedrock API invocations. -The requirements.txt file contains all necessary dependencies for this sample application to work. - -## Step 2: - -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: - -``` -pip install virtualenv -python3.10 -m venv venv -``` - -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: - -``` -cd venv -cd bin -source activate -cd ../../ -``` - -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: - -``` -pip install -r requirements.txt -``` - -## Step 3: - -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: - -``` -profile_name= -``` - -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! - -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 12 in the document_generator.py file to set the appropriate region: - -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') -``` - -Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the invoke_llm() function in the document_generator.py to look like: - -```python -def invoke_llm(bedrock, user_input, doc_template) -> str: - """ - Creates the initial version of the document based on the details provided by the user. - :param bedrock: The Amazon Bedrock client that will be used to orchestrate the LLM. - :param user_input: The details the user is providing to generate the first draft of the document. - :param doc_template: The document template that the output of the LLM should conform to, to help format and structure - it more accordingly - :return: The initial document formatted according to the document template that you pass in with the details provided - by the user on the front end. - """ - - # Setup Prompt - This prompt passes in the document template and the user input to generate the first draft of the - # document the user is looking to create - prompt_data = f""" - -Human: - -Generate a document based on the user input and the instructions and format provided in the Document Template below -The tehcnical document should be human readable, well formatted, and broken into the relveant sections. -Response should be in valid Markdown syntax -### - - -{doc_template} - -### - -{user_input} - -### - -Assistant: Here is a draft based on the provided user input and template - -""" - # Add the prompt to the body to be passed to the Bedrock API along with parameters - body = json.dumps({"prompt": prompt_data, - "max_tokens_to_sample": 5000, - "temperature": .2, - "stop_sequences": [] - }) - # configure the modelID of the model you are trying to use - modelId = "anthropic.claude-v2" # change this to use a different version from the model provider if you want to switch - accept = "application/json" - contentType = "application/json" - # Call the Bedrock API, and invoke the LLM Model of your choice - response = bedrock.invoke_model( - body=body, modelId=modelId, accept=accept, contentType=contentType - ) - # Parse the Response and store it in the llmOutput variable - response_body = json.loads(response.get('body').read()) - llmOutput = response_body.get('completion') - # Return the LLM response - return llmOutput -``` -You can also change the invoke_llm_refine() function within the document_generator.py file to look like: - -```python -def invoke_llm_refine(bedrock, user_feedback, previous_version, doc_template) -> str: - """ - This function is specifically focused on refining the document created by invoke_llm, and refining it based on the feedback - the user is passing in through the frontend. - :param bedrock: The Amazon Bedrock client that will be used to orchestrate the LLM. - :param user_feedback: The feedback the user provides through the frontend that contains the addition/changes they would like - to be made against the original document that was created. - :param previous_version: This is the original document that was created by the invoke_llm function call. - :param doc_template: The document template that the output of the LLM should conform to, to help format and structure - it more accordingly. - :return: The final version of the document that contains the refinements of the original document specified by the user. - """ - # Setup Prompt - This prompt passes in the document template and the user feedback, and the previous version to generate the refined draft of the - # document the user is looking to create. - prompt_data = f""" - -Human: - -Refine and Adjust the provided document based on the user feedback and following structure and format guidelines in the Document Template -Response should be in valid Markdown syntax - -### - -{previous_version} - - - -{user_feedback} - - - -{doc_template} - -### - -Assistant: Here is a modified draft press release based on the provided user feedback - -""" - # Add the prompt to the body to be passed to the Bedrock API along with parameters - body = json.dumps({"prompt": prompt_data, - "max_tokens_to_sample": 5000, - "temperature": .2, - "stop_sequences": [] - }) - # configure the modelID of the model you are trying to use - modelId = "anthropic.claude-v2" # change this to use a different version from the model provider if you want to switch - accept = "application/json" - contentType = "application/json" - # Call the Bedrock API, and invoke the LLM Model of your choice - response = bedrock.invoke_model( - body=body, modelId=modelId, accept=accept, contentType=contentType - ) - # Parse the Response and store it in the llmOutput variable - response_body = json.loads(response.get('body').read()) - llmOutput = response_body.get('completion') - # Return the LLM response - return llmOutput -``` -You can then change the modelId variable to the model of your choice. - -## Step 4: - -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: - -``` -streamlit run app.py -``` - -As soon as the application is up and running in your browser of choice you can begin generating documents based on your specific formatting and details, while also being able to add refinements along the way. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/requirements.txt index 85ace105..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-document-generator-poc/requirements.txt @@ -1,52 +1,5 @@ -altair==5.1.2 -attrs==23.1.0 -blinker==1.7.0 -boto3==1.28.79 -botocore==1.31.79 -cachetools==5.3.2 -certifi==2023.7.22 -charset-normalizer==3.3.2 -click==8.1.7 -gitdb==4.0.11 -GitPython==3.1.41 -idna==3.4 -importlib-metadata==6.8.0 -Jinja2==3.1.3 -jmespath==1.0.1 -jsonschema==4.19.2 -jsonschema-specifications==2023.7.1 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -mdurl==0.1.2 -numpy==1.26.1 -packaging==23.2 -pandas==2.1.2 -Pillow==10.2.0 -pip==23.3 -protobuf==4.25.0 -pyarrow==14.0.1 -pydeck==0.8.1b0 -Pygments==2.16.1 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -referencing==0.30.2 -requests==2.31.0 -rich==13.6.0 -rpds-py==0.12.0 -s3transfer==0.7.0 -setuptools==68.2.0 -six==1.16.0 -smmap==5.0.1 -streamlit==1.30.0 -tenacity==8.2.3 -toml==0.10.2 -toolz==0.12.0 -tornado==6.3.3 -typing_extensions==4.8.0 -tzdata==2023.3 -tzlocal==5.2 -urllib3==1.26.18 -validators==0.22.0 -wheel==0.41.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.projen/deps.json new file mode 100644 index 00000000..a7b559b5 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.projen/deps.json @@ -0,0 +1,39 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "langchain-community", + "type": "runtime" + }, + { + "name": "langchain-experimental", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.1", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/README.md index 4185e8b3..24b9727a 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/README.md @@ -1,133 +1,95 @@ -# Amazon-Bedrock-GenAI-Dynamic-Prompting-Explained-POC +# Amazon Bedrock GenAI Dynamic Prompt Explained POC + +## Overview of Solution This is sample code that can be used to provide a hands on explanation as to how Dynamic Prompting works in relation to Gen AI. The application is constructed with a simple streamlit frontend where users can ask questions against a Amazon Bedrock supported LLM and get a deeper understanding of how few-shot and dynamic prompting works. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock GenAI Dynamic Prompt Explained POC functionality](images/demo.gif) + +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock in a similar fashion to ChatGPT, in this case the application has a strong focus on demonstrating on how prompts are dynamically selected based on the user inputted question. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') + + +When a user interacts with the POC, the flow is as follows: + +1. The user makes a "zero-shot" request to the streamlit frontend. (app.py`) + +1. The application performs a semantic search of the users query against the 1200+ prompts. (`prompt_finder_and_invoke_llm.py`) + +1. The application returns the 3 most semantically similar prompts, and creates a final prompt that contains the 3 returned prompts along with users query (few-shot prompting) (`prompt_finder_and_invoke_llm.py`) + +1. The final prompt is passed into Amazon Bedrock to generate an answer to the users question (`prompt_finder_and_invoke_llm.py`) + +1. The final answer is generated by Amazon Bedrock and displayed on the frontend application along with 3 most semantically similar prompts (`app.py`) -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: -1. The user makes a "zero-shot" request to the streamlit frontend. (app.py). -2. The application performs a semantic search of the users query against the 1200+ prompts. (prompt_finder_and_invoke_llm.py). -3. The application returns the 3 most semantically similar prompts, and creates a final prompt that contains the 3 returned prompts along with users query (few-shot prompting) (prompt_finder_and_invoke_llm.py). -4. The final prompt is passed into Amazon Bedrock to generate an answer to the users question (prompt_finder_and_invoke_llm.py). -5. The final answer is generated by Amazon Bedrock and displayed on the frontend application along with 3 most semantically similar prompts (app.py). # How to use this Repo: ## Prerequisites: -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.9 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). - -## Step 1: - -The first step of utilizing this repo is performing a git clone of the repository. - -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` - -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 4 key files, -the app.py file, the prompt_finder_and_invoke_llm.py file, the chat_history_prompt_generator.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The prompt_finder_and_invoke_llm.py file houses the logic of the application, including the semantic search against the prompt repository and prompt formatting logic and the Amazon Bedrock API invocations. -The chat_history_prompt_generator.py houses the logic required to preserve session state and to dynamically inject the conversation history into prompts to allow for follow-up questions and conversation summary. -The requirements.txt file contains all necessary dependencies for this sample application to work. - -## Step 2: - -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: - -``` -pip install virtualenv -python3.10 -m venv venv -``` - -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: - -``` -cd venv -cd bin -source activate -cd ../../ -``` - -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: - -``` -pip install -r requirements.txt -``` - -## Step 3: - -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: - -``` -profile_name= -``` - -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! - -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 23 in the prompt_finder_and_invoke_llm.py file to set the appropriate region: - -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') -``` - -Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the llm_answer_generator() function in the prompt_finder_and_invoke_llm.py to look like: - -```python -def llm_answer_generator(question_with_prompt): - """ - This function is used to invoke Amazon Bedrock using the finalized prompt that was created by the prompt_finder(question) - function. - :param question_with_prompt: This is the finalized prompt that includes semantically similar prompts, chat history, - and the users question all in a proper multi-shot format. - :return: The final answer to the users question. - """ - # body of data with parameters that is passed into the bedrock invoke model request - # TODO: TUNE THESE PARAMETERS AS YOU SEE FIT - body = json.dumps({"prompt": question_with_prompt, - "max_tokens_to_sample": 8191, - "temperature": 0, - "top_k": 250, - "top_p": 0.5, - "stop_sequences": [] - }) - # configure model specifics such as specific model - modelId = 'anthropic.claude-v2' - accept = 'application/json' - contentType = 'application/json' - # Invoking the bedrock model with your specifications - response = bedrock.invoke_model(body=body, - modelId=modelId, - accept=accept, - contentType=contentType) - # the body of the response that was generated - response_body = json.loads(response.get('body').read()) - # retrieving the specific completion field, where you answer will be - answer = response_body.get('completion') - # returning the answer as a final result, which ultimately gets returned to the end user - return answer -``` -You can then change the modelId variable to the model of your choice. -## Step 4: - -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: - -``` -streamlit run app.py -``` - -As soon as the application is up and running in your browser of choice you can begin asking zero-shot questions and leveraging this app as you would ChatGPT while also seeing the power of dynamic prompting. +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. + + + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `prompt_finder_and_invoke_llm.py` - Houses the logic of the application, including the prompt formatting logic and Amazon Bedrock API invocations. + + + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc + ``` + +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` + +1. create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: + + ```zsh + profile_name= + ``` + + +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 12 in the prompt_finder_and_invoke_llm.py file to set the appropriate region: + + ```zsh + bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') + ``` + + +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. + +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) + diff --git a/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/requirements.txt index 2c877c41..eb14cd31 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-genai-dynamic-prompting-explained-poc/requirements.txt @@ -1,122 +1,8 @@ -aiohttp==3.9.2 -aiosignal==1.3.1 -altair==5.1.2 -annotated-types==0.5.0 -anyio==3.7.1 -async-timeout==4.0.3 -attrs==23.1.0 -awscli==1.29.61 -backoff==2.2.1 -bcrypt==4.0.1 -blinker==1.6.2 -boto3==1.28.61 -botocore==1.31.61 -cachetools==5.3.1 -certifi==2023.7.22 -charset-normalizer==3.3.0 -chroma-hnswlib==0.7.3 -chromadb==0.4.13 -click==8.1.7 -colorama==0.4.4 -coloredlogs==15.0.1 -dataclasses-json==0.6.1 -docutils==0.16 -exceptiongroup==1.1.3 -fastapi==0.109.1 -filelock==3.12.4 -flatbuffers==23.5.26 -frozenlist==1.4.0 -fsspec==2023.9.2 -gitdb==4.0.10 -GitPython==3.1.41 -h11==0.14.0 -httptools==0.6.0 -huggingface-hub==0.17.3 -humanfriendly==10.0 -idna==3.4 -importlib-metadata==6.8.0 -importlib-resources==6.1.0 -Jinja2==3.1.3 -jmespath==1.0.1 -joblib==1.3.2 -jsonpatch==1.33 -jsonpointer==2.4 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -langchain==0.1.11 -langchain-community==0.0.31 -langsmith==0.1.17 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -marshmallow==3.20.1 -mdurl==0.1.2 -monotonic==1.6 -mpmath==1.3.0 -multidict==6.0.4 -mypy-extensions==1.0.0 -networkx==3.1 -nltk==3.8.1 -numpy==1.26.0 -onnxruntime==1.16.0 -overrides==7.4.0 -packaging==23.2 -pandas==2.1.1 -Pillow==10.2.0 -pip==23.3 -posthog==3.0.2 -protobuf==4.24.4 -pulsar-client==3.3.0 -pyarrow==14.0.1 -pyasn1==0.5.0 -pydantic==2.4.2 -pydantic_core==2.10.1 -pydeck==0.8.1b0 -Pygments==2.16.1 -PyPika==0.48.9 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -PyYAML==6.0.1 -referencing==0.30.2 -regex==2023.10.3 -requests==2.31.0 -rich==13.6.0 -rpds-py==0.10.4 -rsa==4.7.2 -s3transfer==0.7.0 -safetensors==0.4.0 -scikit-learn==1.3.1 -scipy==1.11.3 -sentencepiece==0.1.99 -sentence-transformers==2.6.1 -setuptools==65.5.1 -six==1.16.0 -smmap==5.0.1 -sniffio==1.3.0 -SQLAlchemy==2.0.21 -starlette==0.35.0 -streamlit==1.30.0 -sympy==1.12 -tenacity==8.2.3 -threadpoolctl==3.2.0 -tokenizers==0.14.1 -toml==0.10.2 -toolz==0.12.0 -torch==2.1.0 -torchvision==0.16.0 -tornado==6.3.3 -tqdm==4.66.1 -typer==0.9.0 -typing_extensions==4.8.0 -typing-inspect==0.9.0 -tzdata==2023.3 -tzlocal==5.1 -urllib3==1.26.18 -uvicorn==0.23.2 -uvloop==0.17.0 -validators==0.22.0 -watchfiles==0.20.0 -websockets==11.0.3 -wheel==0.38.4 -yarl==1.9.2 -zipp==3.17.0 \ No newline at end of file +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +langchain-community +langchain-experimental +langchain>=0.1.0, <0.2.0 +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/README.md index 6b0378ae..cc359c95 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/README.md @@ -1,89 +1,90 @@ -# Amazon-Bedrock-Guardrails-POC +# Amazon Bedrock Guardrails POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock Guardrails to help prevent prompt-injection attacks and prevent unintended responses from the LLM. The application is constructed with a simple streamlit frontend where users can input zero shot requests to Claude 3, with Amazon Bedrock Guardrails in place to prevent malicious prompts and responses. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Guardrails POC functionality](images/demo.gif) + +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock Guardrails to demonstrate its ability to prevent malicious prompts and responses. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: +When a user interacts with the POC, the flow is as follows: -1. The user inserts a text question into to the streamlit app. (app.py). -2. The streamlit app, takes the text inserted by the user and is passed into an Amazon Bedrock Guardrail to check for prompt injection. If the prompt is detected as malicious or triggers the guardrail a response will be returned to the end user saying the request is blocked (invoke_model_with_guardrails.py). -3. If the prompt does not trigger the guardrail it is passed into the bedrock model the user has specified (invoke_model_with_guardrails.py). -4. A response is returned by the Amazon Bedrock Model of choice and is passed into the Amazon Bedrock Guardrail (invoke_model_with_guardrails.py). If the response is detected as malicious or triggers the guardrail a response will be returned to the end user saying the request is blocked (invoke_model_with_guardrails.py). -5. If the response does not trigger a guardrail, a natural language response is returned to the end user answering the initial text question inserted by the end user (app.py). +1. The user inserts a text question into to the streamlit app. (`app.py`) -# How to use this Repo: +1. The streamlit app, takes the text inserted by the user and is passed into an Amazon Bedrock Guardrail to check for prompt injection. If the prompt is detected as malicious or triggers the guardrail a response will be returned to the end user saying the request is blocked (`invoke_model_with_guardrails.py`) -## Prerequisites: +1. If the prompt does not trigger the guardrail it is passed into the bedrock model the user has specified (`invoke_model_with_guardrails.py`) -1. Amazon Bedrock Access and CLI Credentials. -2. Create an Amazon Bedrock Guardrail, information on how to do that can be found [here](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-create.html) -2. Ensure Python 3.1- installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3100/). +1. A response is returned by the Amazon Bedrock Model of choice and is passed into the Amazon Bedrock Guardrail (`invoke_model_with_guardrails.py`). If the response is detected as malicious or triggers the guardrail a response will be returned to the end user saying the request is blocked (`invoke_model_with_guardrails.py`) -## Step 1: +1. If the response does not trigger a guardrail, a natural language response is returned to the end user answering the initial text question inserted by the end user (`app.py`) -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the invoke_model_with_guardrails.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -invoke_model_with_guardrails.py file houses the logic of the application, including the Amazon Bedrock Guardrail and Amazon Bedrock API invocations. -The requirements.txt file contains all necessary dependencies for this sample application to work. -## Step 2: +# How to use this Repo: -Set up a python virtual environment in the root of this specific POCs directory and ensure that you are using Python 3.10. This can be done by running the following commands: +## Prerequisites: + +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -``` -pip install virtualenv -python3.10 -m venv venv -``` +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -source venv/bin/activate -``` -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this specific POCs directory in your terminal: +## Steps +1. Clone the repository to your local machine. -``` -pip install -r requirements.txt -``` + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `invoke_model_with_guardrails.py` - Houses the logic of the application, including the prompt formatting logic and Amazon Bedrock API invocations. + + -## Step 3: +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc + ``` -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -``` -profile_name= -region_name= +1. create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: + + ```zsh + profile_name= + region_name= guardrail_identifier= guardrail_version= (this is just a number i.e. 1,2,3 etc...) -``` - -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! + ``` -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin asking text questions and generating natural language responses having Amazon Bedrock Guardrails preventing malicious requests and responses. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/requirements.txt index 0380fae3..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-guardrails-poc/requirements.txt @@ -1,3 +1,5 @@ -boto3==1.34.100 -python-dotenv==1.0.0 -streamlit==1.34.0 \ No newline at end of file +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.projen/deps.json new file mode 100644 index 00000000..b9b43281 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.projen/deps.json @@ -0,0 +1,30 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "pillow", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/README.md index ad9b4679..394faf2f 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/README.md @@ -1,94 +1,67 @@ -# Amazon-Bedrock-Image-Generation-POC +# Amazon Bedrock Image Generation POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement an image generation use case. The application is constructed with a simple streamlit frontend where users can input text requests to generate images based on the text input. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Image Generation POC functionality](images/demo.gif) + +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to create images based on text input requests. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: - -![Alt text](images/architecture.png "POC Architecture") - -When a user interacts with the GenAI app, the flow is as follows: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -1. The user inputs a text request asking to generate an image. (app.py). -2. The streamlit app, takes the text input, and invokes Amazon Bedrock to generate an image (image_generation.py). -3. The image created by Amazon Bedrock is returned and displayed on the streamlit app (app.py). -# How to use this Repo: - -## Prerequisites: +When a user interacts with the POC, the flow is as follows: -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). +1. The user inputs a text request asking to generate an image. (`app.py`) -## Step 1: +1. The streamlit app, takes the text input, and invokes Amazon Bedrock to generate an image (`image_generation.py`) -The first step of utilizing this repo is performing a git clone of the repository. +1. The image created by Amazon Bedrock is returned and displayed on the streamlit app (`app.py`) -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the image_generation.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The image_generation.py file houses the logic of the application, including the Amazon Bedrock API invocations to generate an image. -The requirements.txt file contains all necessary dependencies for this sample application to work. -## Step 2: -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: - -``` -pip install virtualenv -python3.10 -m venv venv -``` - -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: - -``` -cd venv -cd bin -source activate -cd ../../ -``` - -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: +# How to use this Repo: -``` -pip install -r requirements.txt -``` +## Prerequisites: -## Step 3: +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -``` -profile_name= -``` -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! -Depending on the region and model that you are planning to use with Amazon Bedrock (please note that only a few models can generate images based on text input), you may need to reconfigure line 13 & 31 in the image_generation.py file: +## Steps +1. Clone the repository to your local machine. -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock.us-east-1.amazonaws.com') + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + -modelId = 'stability.stable-diffusion-xl-v1' -``` +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc + ``` -## Step 4: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin creating images! diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/requirements.txt index cc6b8d89..0f4c6dff 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-generation-poc/requirements.txt @@ -1,58 +1,6 @@ -altair==5.1.2 -attrs==23.1.0 -awscli==1.29.60 -blinker==1.6.2 -boto3==1.28.60 -botocore==1.31.60 -cachetools==5.3.1 -certifi==2023.7.22 -charset-normalizer==3.3.0 -click==8.1.7 -colorama==0.4.4 -docutils==0.16 -gitdb==4.0.10 -GitPython==3.1.41 -idna==3.4 -importlib-metadata==6.8.0 -Jinja2==3.1.3 -jmespath==1.0.1 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -mdurl==0.1.2 -numpy==1.26.0 -packaging==23.2 -pandas==2.1.1 -Pillow==10.2.0 -pip==23.3 -protobuf==4.24.4 -pyarrow==14.0.1 -pyasn1==0.5.0 -pydeck==0.8.1b0 -Pygments==2.16.1 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -PyYAML==6.0.1 -referencing==0.30.2 -requests==2.31.0 -rich==13.6.0 -rpds-py==0.10.3 -rsa==4.7.2 -s3transfer==0.7.0 -setuptools==65.5.1 -six==1.16.0 -smmap==5.0.1 -streamlit==1.30.0 -tenacity==8.2.3 -toml==0.10.2 -toolz==0.12.0 -tornado==6.3.3 -typing_extensions==4.8.0 -tzdata==2023.3 -tzlocal==5.1 -urllib3==1.26.18 -validators==0.22.0 -wheel==0.38.4 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +pillow +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/README.md index 681c795a..bd4e79c5 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/README.md @@ -1,88 +1,88 @@ -# Amazon-Bedrock-Guardrails-POC +# Amazon Bedrock Image Generation with Guardrails + +## Overview of Solution This sample code demonstrates using Amazon Bedrock Guardrails to prevent Stability Diffusion LLM from generating harmful, obscene, or violent images. The application features a streamlit frontend where users input zero-shot requests to Claude 3. Amazon Bedrock Guardrails determine whether to proceed with generating images using the Stability Diffusion model. -![Alt text](images/GenerateImageWithGuardrails.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Image Generation with Guardrails functionality](images/demo.gif) + +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to create images based on text input requests with security guardrails. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with this Generative AI app, the flow is as follows: +When a user interacts with the POC, the flow is as follows: 1. The user inserts a text question into to the streamlit app. (app.py). -2. The streamlit app, takes the text inserted by the user and is passed to Claude LLM with Guardrail id to check for prompt which is acceptable. If the prompt is detected as malicious or triggers the guardrail, a response (Blocked Messaging statement on Bedrock Guardrails) will be returned to the end user saying the request is blocked with a message "Inappropriate prompt!!" (image_generation_guardrails.py). -3. If the prompt does not trigger the guardrail, it is passedto the model Stability diffusion model to generate images. -# How to use this Repo: +1. The streamlit app, takes the text inserted by the user and is passed to Claude LLM with Guardrail id to check for prompt which is acceptable. If the prompt is detected as malicious or triggers the guardrail, a response (Blocked Messaging statement on Bedrock Guardrails) will be returned to the end user saying the request is blocked with a message "Inappropriate prompt!!" (image_generation_guardrails.py). -## Prerequisites: +1. If the prompt does not trigger the guardrail, it is passedto the model Stability diffusion model to generate images. -1. Amazon Bedrock Access and CLI Credentials. -2. Create an Amazon Bedrock Guardrail, information on how to do that can be found [here](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-create.html) -Put message blocking content from Bedrock console and initialize variable "guardrail_msg" (app.py) -2. Ensure Python 3.10- installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3100/). -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` +# How to use this Repo: + +## Prerequisites: -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the invoke_model_with_guardrails.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -invoke_model_with_guardrails.py file houses the logic of the application, including the Amazon Bedrock Guardrail and Amazon Bedrock API invocations. -The requirements.txt file contains all necessary dependencies for this sample application to work. +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -## Step 2: +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -Set up a python virtual environment in the root of this specific POCs directory and ensure that you are using Python 3.10. This can be done by running the following commands: -``` -pip install virtualenv -python3.10 -m venv venv -``` +1. Create an Amazon Bedrock Guardrail, information on how to do that can be found [here](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-create.html) -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -source venv/bin/activate -``` +## Steps +1. Clone the repository to your local machine. -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this specific POCs directory in your terminal: + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `invoke_model_with_guardrails.py` - the logic of the application, including the Amazon Bedrock Guardrail and Amazon Bedrock API invocations. + + -``` -pip install -r requirements.txt -``` +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc + ``` -## Step 3: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: -``` -profile_name= + ```zsh + profile_name= region_name= guardrail_identifier= guardrail_version= (this is just a number i.e. 1,2,3 etc...) -``` - -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! + ``` -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin asking text questions and generating natural language responses having Amazon Bedrock Guardrails preventing malicious requests and responses. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/image_generation_guardrails.py b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/image_generation_guardrails.py index 764e6373..56a128f8 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/image_generation_guardrails.py +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/image_generation_guardrails.py @@ -105,7 +105,7 @@ def image_generator(question): # saving the generated image locally, and specifying the path to which the generated image was saved #img.save('my-image.jpeg') ts=time.time() - imagename='./images/my-image'+str(ts)+'.jpeg' + imagename='./generated-images/my-image'+str(ts)+'.jpeg' img.save(imagename) # returning the path of the saved image, so that it can be displayed on the frontend of the streamlit app diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/images/GenerateImageWithGuardrails.gif b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/images/demo.gif similarity index 100% rename from genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/images/GenerateImageWithGuardrails.gif rename to genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/images/demo.gif diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/requirements.txt index 0380fae3..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-image-guardrails-poc/requirements.txt @@ -1,3 +1,5 @@ -boto3==1.34.100 -python-dotenv==1.0.0 -streamlit==1.34.0 \ No newline at end of file +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.gitignore index b2dedc92..70ae3a77 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.gitignore +++ b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.gitignore @@ -1,22 +1,85 @@ -# Ignore .env file +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py .env - -# Ignore output folder -output/ - -# Ignore venv folder +.venv +env/ venv/ - -# Ignore Python cache files -__pycache__/ -*.pyc -*.pyo -*.pyd - -# Ignore IDE-specific files (optional, but often useful) -.vscode/ -.idea/ - -# Ignore OS-specific files (optional) -.DS_Store -Thumbs.db +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/README.md index 364fcc02..5254a326 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/README.md @@ -1,107 +1,126 @@ -# Amazon-Bedrock-Intelligent-Document-Processing-Pipeline-POC +# Amazon Bedrock Intelligent Document Processing (IDP) POC -This is sample code demonstrating the use of Amazon Bedrock and Generative AI incorporated into an Intelligent Document Processing (IDP) pipeline using user-uploaded documents. The application is constructed with a simple streamlit frontend where users can upload various document formats and perform different IDP actions such as text extraction, document summarization and classification, entity recognition, and Q&A to satisfy a broad range of use cases. +## Overview of Solution -![Alt text](images/demo.gif) -# **Goal of this Repo:** +This is sample code demonstrating the use of Amazon Bedrock and Generative AI incorporated into an Intelligent Document Processing (IDP) pipeline using user-uploaded documents. The application is constructed with a simple streamlit frontend where users can upload various document formats and perform different IDP actions such as text extraction, document summarization and classification, entity recognition, and Q&A to satisfy a broad range of use cases. -The goal of this repo is to provide users the ability to use various Amazon AI services utilized in an IDP pipeline combined with Amazon Bedrock to improve performance, complete tasks faster, and limit human review. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. - -The architecture and flow of the sample application will be: - - -![Alt text](images/architecture.png "POC Architecture") - -When a user interacts with the GenAI app, the flow is as follows: - -1. The user selects and uploads a document to the streamlit frontend (upload_doc_to_s3.py). -2. The document is uploaded to an Amazon S3 bucket (upload_doc_to_s3.py, s3_utils.py) -3. The raw text and key-value pairs are extracted from the document using Amazon Textract (extract_text_with_textract.py, textract_utils.py) -4. The extracted key-value pairs are grammatically corrected using Amazon Bedrock, where the enriched output is saved to the local directory (enrich_doc_with_bedrock.py, bedrock_utils.py) -5. The enriched output is then analyzed by Amazon Comprehend to detect entities such as people, organizations, locations, and more (entity_recognition_with_comprehend.py, comprehend_utils.py). -6. The enriched output is then passed to Amazon Bedrock for document classification, summarization, and Q&A tasks. Bedrock’s multimodal capabilities can also be compared at each these stages by analyzing the document as is (classify_doc_with_bedrock.py, summarize_doc_with_bedrock.py, doc_qa_with_bedrock.py, bedrock_utils.py) - -# How to use this Repo: - -## Prerequisites: +![A gif of a screen recording show casing the Amazon Bedrock Intelligent Document Processing (IDP) POC functionality](images/demo.gif) -1. Amazon Bedrock, Amazon Textract, Amazon Comprehend Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.11 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). -3. An Amazon S3 bucket with permissions to upload and list objects. This is required to upload your document. -## Step 1: +## Goal of this POC +The goal of this repo is to provide users the ability to use various Amazon AI services utilized in an IDP pipeline combined with Amazon Bedrock to improve performance, complete tasks faster, and limit human review. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The first step of utilizing this repo is performing a git clone of the repository. +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 14 key files: -* app.py: The main streamlit app entry point. -* pages/welcome.py: The welcome page providing an overview of the IDP stages. -* pages/upload_doc_to_s3.py: The streamlit page that houses the logic to select a document or file to upload. -* pages/extract_text_with_textract.py: The streamlit page that houses the logic to invoke a new Textract job. -* pages/enrich_doc_with_bedrock.py: The streamlit page that houses the logic to read the key-value pair text file (output/key_value.txt) and invoke Bedrock to enrich the document by correcting any grammar mistakes or incorrect text extractions from the Textract job. The enriched result is saved as a local text file (output/enriched_output.txt). -* pages/entity_recognition_with_comprehend.py: The streamlit page that houses the logic to invoke Comprehend to perform entitiy recognition on the contents in the enriched output file (output/enriched_output.txt). -* pages/classify_doc_with_bedrock.py: The streamlit page that houses the logic to provide the user the option to classify the document from a select category of classes using either Bedrock's text or multimodal capabilities. A user can choose to have Bedrock read the enriched output file (output/enriched_output.txt) or read the file stored in S3 as an image to classify the document. -* pages/summarize_doc_with_bedrock.py: The streamlit page that houses the logic to provide the user the option to summarize the document using either Bedrock's text or multimodal capabilities. A user can choose to have Bedrock read the enriched output file (output/enriched_output.txt) or read the file stored in S3 as an image to summarize the document. -* pages/doc_qa_with_bedrock.py: The streamlit page that houses the logic to provide the user the option to ask questions about the document using either Bedrock's text or multimodal capabilities. A user can choose to have Bedrock read the enriched output file (output/enriched_output.txt) or read the file stored in S3 as an image to answer user queries regarding the document's contents. -* idp/bedrock_utils.py: The file containing the logic for document enrichment, classification, summarization, and question-answering by interacting with Amazon Bedrock. These interactions are performed by sending a structured prompt containing the relevant text or image data to the Bedrock model via API calls. The prompt includes instructions for the model, such as correcting grammar, classifying documents into predefined categories, or summarizing content, and the model's responses are parsed and returned as usable output. -* idp/comprehend_utils.py: The file containing the logic to invoke Amazon Comprehend, which will perform entity recognition using the default pre-trained model to detect entities such as names, dates, organizations, etc. -* idp/s3_utils.py: The file containing the logic to upload a file to S3 and list any current documents stored in the selected bucket. -* idp/textract_utils.py: The file containing the logic to start a Textract job that analyzes the document and extracts the raw text and key-value pairs from the document, saving both as local text files (extracted_text.txt and key_value.txt) to the "output" folder. -* requirements.txt: The file containing all necessary dependencies for this sample application to work. +When a user interacts with the POC, the flow is as follows: -## Step 2: +1. The user selects and uploads a document to the streamlit frontend (upload_doc_to_s3.py). -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: +1. The document is uploaded to an Amazon S3 bucket (upload_doc_to_s3.py, s3_utils.py) -``` -pip install virtualenv -python3.11 -m venv venv -``` +1. The raw text and key-value pairs are extracted from the document using Amazon Textract (extract_text_with_textract.py, textract_utils.py) -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: +1. The extracted key-value pairs are grammatically corrected using Amazon Bedrock, where the enriched output is saved to the local directory (enrich_doc_with_bedrock.py, bedrock_utils.py) -``` -source venv/bin/activate -``` +1. The enriched output is then analyzed by Amazon Comprehend to detect entities such as people, organizations, locations, and more (entity_recognition_with_comprehend.py, comprehend_utils.py). -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: +1. The enriched output is then passed to Amazon Bedrock for document classification, summarization, and Q&A tasks. Bedrock’s multimodal capabilities can also be compared at each these stages by analyzing the document as is (classify_doc_with_bedrock.py, summarize_doc_with_bedrock.py, doc_qa_with_bedrock.py, bedrock_utils.py -``` -pip install -r requirements.txt -``` -## Step 3: -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain your AWS profile, along with the name of your S3 bucket for uploaded documents, as shown below: -``` -profile_name= -save_folder= -``` +# How to use this Repo: -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! +## Prerequisites: +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. + + +1. Access to Amazon Textract and Amazon Comprehend via the AWS CLI + +1. An Amazon S3 bucket with permissions to upload and list objects. This is required to upload your document. Please note the name of the bucket, you will need this. + + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `pages/welcome.py` - The welcome page providing an overview of the Intelligent Document Processing (IDP) stages. + + * `pages/upload_doc_to_s3.py` - The streamlit page that houses the logic to select a document or file to upload. + + * `pages/extract_text_with_textract.py` - The streamlit page that houses the logic to invoke Textract to extract the raw text and key-value pairs from the document. + + * `pages/enrich_doc_with_bedrock.py` - The streamlit page that houses the logic to read the key-value pair text file (output/key_value.txt) and invoke Bedrock to enrich the document by correcting any grammar mistakes or incorrect text extractions from the Textract job. The enriched result is saved as a local text file (output/enriched_output.txt). + + * `pages/entity_recognition_with_comprehend.py` - The streamlit page that houses the logic to invoke Comprehend to perform entitiy recognition on the contents in the enriched output file (output/enriched_output.txt). + + * `pages/classify_doc_with_bedrock.py` - The streamlit page that houses the logic to provide the user the option to classify the document from a select category of classes using either Bedrock's text or multimodal capabilities. A user can choose to have Bedrock read the enriched output file (output/enriched_output.txt) or read the file stored in S3 as an image to classify the document. + + * `pages/summarize_doc_with_bedrock.py` - The streamlit page that houses the logic to provide the user the option to summarize the document using either Bedrock's text or multimodal capabilities. A user can choose to have Bedrock read the enriched output file (output/enriched_output.txt) or read the file stored in S3 as an image to summarize the document. + + * `pages/doc_qa_with_bedrock.py` - The streamlit page that houses the logic to provide the user the option to ask questions about the document using either Bedrock's text or multimodal capabilities. A user can choose to have Bedrock read the enriched output file (output/enriched_output.txt) or read the file stored in S3 as an image to answer user queries regarding the document's contents. + + * `idp/bedrock_utils.py` - The file containing the logic for document enrichment, classification, summarization, and question-answering by interacting with Amazon Bedrock. These interactions are performed by sending a structured prompt containing the relevant text or image data to the Bedrock model via API calls. The prompt includes instructions for the model, such as correcting grammar, classifying documents into predefined categories, or summarizing content, and the model's responses are parsed and returned as usable output. + + * `idp/comprehend_utils.py` - The file containing the logic to invoke Amazon Comprehend, which will perform entity recognition using the default pre-trained model to detect entities such as names, dates, organizations, etc. + + * `idp/s3_utils.py` - The file containing the logic to upload a file to S3 and list any current documents stored in the selected bucket. + + * `idp/textract_utils.py` - The file containing the logic to start a Textract job that analyzes the document and extracts the raw text and key-value pairs from the document, saving both as local text files (extracted_text.txt and key_value.txt) to the "output" folder. + + + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc + ``` + +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` + +1. Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain your AWS profile, along with the name of your S3 bucket for uploaded documents, as shown below: + + ```zsh + + profile_name= + save_folder= + ``` + + +1. Since this repository is configured to leverage Claude 3.5 Sonnet, the prompt payload is structured in a different format compared to previous models and other model providers. If you wanted to leverage other Amazon Bedrock models you can change the Bedrock invocation function in each file, modifying the body parameters using this guide depending on the model ID. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure each file that utilizes Bedrock set to the appropriate region. Each of these files are configured as shown below: -``` -client = boto3.client("bedrock-runtime", region_name="us-west-2") -model_id = "anthropic.claude-3-5-sonnet-20240620-v1:0" -``` - -Since this repository is configured to leverage Claude 3.5 Sonnet, the prompt payload is structured in a different format compared to previous models and other model providers. If you wanted to leverage other Amazon Bedrock models you can change the Bedrock invocation function in each file, modifying the body parameters using this guide depending on the model ID. + ```zsh + + client = boto3.client("bedrock-runtime", region_name="us-west-2") + model_id = "anthropic.claude-3-5-sonnet-20240620-v1:0" + ``` -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin the IDP pipeline by starting at the first stage and uploading a document to your S3 bucket. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/requirements.txt index 14981811..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-intelligent-document-processing-poc/requirements.txt @@ -1,83 +1,5 @@ -aiohttp==3.9.2 -aiosignal==1.3.1 -altair==5.1.1 -annotated-types==0.5.0 -anyio==3.7.1 -async-timeout==4.0.3 -attrs==23.1.0 -blinker==1.6.2 -boto3==1.28.59 -botocore==1.31.59 -cachetools==5.3.1 -certifi==2023.7.22 -charset-normalizer==3.3.0 -click==8.1.7 -dataclasses-json==0.6.1 -exceptiongroup==1.1.3 -filelock==3.12.4 -frozenlist==1.4.0 -fsspec==2023.9.2 -gitdb==4.0.10 -GitPython==3.1.41 -huggingface-hub==0.17.3 -idna==3.4 -importlib-metadata==6.8.0 -Jinja2==3.1.3 -jmespath==1.0.1 -jsonpatch==1.33 -jsonpointer==2.4 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -langchain==0.1.11 -langsmith==0.1.17 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -marshmallow==3.20.1 -mdurl==0.1.2 -multidict==6.0.4 -mypy-extensions==1.0.0 -numpy==1.26.0 -openai==0.28.1 -packaging==23.2 -pandas==2.1.1 -Pillow==10.2.0 -pip==23.3 -protobuf==4.24.3 -pyarrow==14.0.1 -pydantic==2.4.2 -pydantic_core==2.10.1 -pydeck==0.8.1b0 -Pygments==2.16.1 -pypdf==3.17.0 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -PyYAML==6.0.1 -referencing==0.30.2 -regex==2023.8.8 -requests==2.31.0 -rich==13.6.0 -rpds-py==0.10.3 -s3transfer==0.7.0 -safetensors==0.3.3 -setuptools==65.5.1 -six==1.16.0 -smmap==5.0.1 -sniffio==1.3.0 -SQLAlchemy==2.0.21 -streamlit==1.39.0 -tenacity==8.2.3 -tokenizers==0.13.3 -toml==0.10.2 -toolz==0.12.0 -tornado==6.3.3 -tqdm==4.66.1 -typing_extensions==4.8.0 -typing-inspect==0.9.0 -tzdata==2023.3 -tzlocal==5.0.1 -urllib3==1.26.18 -validators==0.22.0 -wheel==0.38.4 -yarl==1.9.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/README.md index 80b9d7c2..dedf6b7e 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/README.md @@ -1,184 +1,49 @@ -# Amazon-Bedrock-RAG-KnowledgeBases-POC +# Amazon Bedrock Knowledgebases RAG POC -This is sample code demonstrating the use of Amazon Bedrock and Generative AI to create vector embeddings for your data sources using Amazon Bedrock Knowledge bases with the ability ask questions against the stored documents. The application is constructed with a RAG based architecture where users can ask questions against the Knowledge bases. - -![Alt text](images/demo.gif) -# **Goal of this Repo:** - -The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to take natural language questions, and answer questions against Amazon Bedrock Knowledge bases. -This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. +## Overview of Solution -The architecture and flow of the sample application will be: +This is sample code demonstrating the use of Amazon Bedrock and Generative AI to create vector embeddings for your data sources using Amazon Bedrock Knowledge bases with the ability ask questions against the stored documents. The application is constructed with a RAG based architecture where users can ask questions against the Knowledge bases. -![Alt text](images/architecture_diagram.png "POC Architecture") +![A gif of a screen recording show casing the Amazon Bedrock Knowledgebases RAG POC functionality](images/demo.gif) -When a user interacts with the GenAI app, the flow is as follows: -1. The user makes a request to the GenAI app (app.py). -2. The app issues a get contexts query to the Amazon Bedrock Knowledge bases based on the user request. (query_against_knowledgeBases.py) -3. The knowledge bases returns search results related to the relevant documents from the ingested data. (query_against_knowledgeBases.py) -4. The app sends the user request and along with the data retrieved from the Amazon Bedrock Knowlegebases as context in the LLM prompt. (query_against_knowledgeBases.py) -5. The LLM returns a succinct response to the user request based on the retrieved data. (query_against_knowledgeBases.py) -6. The response from the LLM is sent back to the user. (app.py) # How to use this Repo: ## Prerequisites: -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Appropriate permissions to configure Amazon Bedrock Knowledge bases. -3. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). - -## Step 1: - -The first step of utilizing this repo is performing a git clone of the repository. - -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` - -After cloning the repo onto your local machine, open it up in your favorite code editor.The file structure of this repo is broken into 3 key files, -the app.py file, the query_against_knowledgebases.py file and the requirements.txt. -The app.py file houses the frontend application (a streamlit app). -The query_against_knowledgeBases.py file houses the logic for taking a user question and letting the LLM generate a response, this includes both the Knowledge bases get contexts calls and Amazon Bedrock LLM API invocation. -The requirements.txt file contains all necessary dependencies for this sample application to work. - -## Step 2: - -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: - -``` -pip install virtualenv -python3.10 -m venv venv -``` - -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: - -``` -cd venv -cd bin -source activate -cd ../../ -``` - -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: - -``` -pip install -r requirements.txt -``` - -## Step 3: - -Now that we have successfully cloned the repo, created and activated the virtual environment and installed the necessary dependencies, it is time for us to create Amazon Bedrock Knowledge base. - -To create our Amazon Bedrock Knowledge base we will: - -1. Go to the Amazon Bedrock Service homepage within the AWS console and on the left-hand side we will select "Knowledge bases" under the "Orchestration" drop down ![Alt text](images/amazon_bedrock_homepage.png "Amazon Bedrock Homepage") +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -2. We will then click on "Create knowledge base" ![Alt text](images/knowledgeBase_homepage.png "Amazon Bedrock Create Knowledge base") +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -3. In the Knowledge base details section, you can optionally change the default name and provide a description for your knowledge base.In the IAM permissions section, choose an AWS Identity and Access Management (IAM) role that provides Amazon Bedrock permission to access other AWS services. You can let Amazon Bedrock create the service role or choose a custom role that you have created. Optionally, add tags to your knowledge base. Select Next. ![Alt text](images/kb_first_page.png "Knowledge base details") -4. On the Set up data source page, provide the information for the data source to use for the knowledge base: Optionally, change the default Data source name. Provide the S3 URI of the object containing the files for the data source that you prepared. Select Next. ![Alt text](images/kb_datasource_page.png "Set up Data Source") -5. In the Embeddings model section, choose a supported embeddings model to convert your data into vector embeddings for the knowledge base. In the Vector database section, choose Quick create a new vector store and select Next ![Alt text](images/kb_vectordb_page.png "Select Embeddings Model") +## Steps +1. Clone the repository to your local machine. -6. On the Review and create page, check the configuration and details of your knowledge base. Choose Edit in any section that you need to modify. When you are satisfied, select Create knowledge base. - - -## Step 4: - -Now that the requirements have been successfully installed in your virtual environment, your Bedrock Knowledge base is created, we can now begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: - -``` -profile_name= -knowledge_base_id= -``` - -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! - -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 13 and 14 in the query_against_knowledgeBases.py file to change the region: - -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1') -bedrock_agent_runtime = boto3.client('bedrock-agent-runtime','us-east-1') -``` -Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the answer_query() function in the query_against_knowledgeBases.py to look like: - -```python -def answer_query(user_input): - """ - This function takes the user question, queries Amazon Bedrock KnowledgeBases for that question, - and gets context for the question. - Once it has the context, it calls the LLM for the response - :param user_input: This is the natural language question that is passed in through the app.py file. - :return: The answer to your question from the LLM based on the context from the Knowledge Bases. - """ - # Setting primary variables, of the user input - userQuery = user_input - # getting the contexts for the user input from Bedrock knowledge bases - userContexts = get_contexts(userQuery, knowledge_base_id) - - # Configuring the Prompt for the LLM - # TODO: EDIT THIS PROMPT TO OPTIMIZE FOR YOUR USE CASE - prompt_data = f"""\n\nHuman: You are an AI assistant that will help people answer questions they have about [YOUR TOPIC]. Answer the provided question to the best of your ability using the information provided in the Context. - Summarize the answer and provide sources to where the relevant information can be found. - Include this at the end of the response. - Provide information based on the context provided. - Format the output in human readable format - use paragraphs and bullet lists when applicable - Answer in detail with no preamble - If you are unable to answer accurately, please say so. - Please mention the sources of where the answers came from by referring to page numbers, specific books and chapters! - - Question: {userQuery} - - Here is the text you should use as context: {userContexts} - - \n\nAssistant: - - """ - # Configuring the model parameters, preparing for inference - # TODO: TUNE THESE PARAMETERS TO OPTIMIZE FOR YOUR USE CASE - prompt = {"prompt": prompt_data, - "max_tokens_to_sample": 4096, - "temperature": 0.5, - "top_k": 250, - "top_p": 0.5, - "stop_sequences": [] - } + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` - # formatting the prompt as a json string - json_prompt = json.dumps(prompt) - - # Configuring the specific model you are using - modelId = "anthropic.claude-v2:1" # change this to use a different version from the model provider - - # invoking Claude2, passing in our prompt - response = bedrock.invoke_model(body=json_prompt, modelId=modelId, - accept="application/json", contentType="application/json") - - # getting the response from Claude2 and parsing it to return to the end user - response_body = json.loads(response.get('body').read()) - - # the final string returned to the end user - answer = response_body.get('completion') - - # returning the final string to the end user - return answer -``` - -You can then change the modelId variable to the model of your choice. +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc + ``` -## Step 7: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -As soon as you have successfully configured the environment variables and the required code changes, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin asking natural language questions against the data sources that you configured with Knowledge bases. \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/requirements.txt index 8c7c64ee..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-knowledgebases-rag-poc/requirements.txt @@ -1,4 +1,5 @@ -boto3==1.34.84 -botocore==1.34.84 -python-dotenv==1.0.0 -streamlit==1.30.0 \ No newline at end of file +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.projen/deps.json new file mode 100644 index 00000000..a7b559b5 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.projen/deps.json @@ -0,0 +1,39 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "langchain-community", + "type": "runtime" + }, + { + "name": "langchain-experimental", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.1", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/README.md index f2ed4e3b..6f2298a7 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/README.md @@ -1,119 +1,113 @@ -# Amazon-Bedrock-Langchain-RAG-POC +# Amazon Bedrock LangChain RAG POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI using Langchain as orchestrator with the ability ask questions against the stored documents. This sample uses Knowledge bases as to retrieve the stored documents, however you can extend or update this sample to retrieve your stored documents from any Vector DB. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock LangChain RAG POC functionality](images/demo.gif) + -The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to take natural language questions orchestrated using Langchain, and answer questions against your stored documents. +## Goal of this POC +The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI using Langchain as orchestrator to create RAG based applications. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/architecture_diagram.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: +When a user interacts with the POC, the flow is as follows: -1. The user makes a request to the GenAI app (app.py). -2. The app issues a get contexts query to the Amazon Bedrock Knowledge bases using Langchain based on the user request. (query_with_langchain.py) -3. The knowledge bases returns search results related to the relevant documents from the ingested data. (query_with_langchain.py) -4. The app sends the user request and along with the data retrieved from the Amazon Bedrock Knowlegebases as context in the LLM prompt to a LLM available within Bedrock using Langchain. (query_with_langchain.py) -5. The LLM returns a succinct response to the user request based on the retrieved data. (query_with_langchain.py) -6. The response from the LLM is sent back to the user. (app.py) +1. The user makes a request to the GenAI app (`app.py`) -# How to use this Repo: +1. The app issues a get contexts query to the Amazon Bedrock Knowledge bases using Langchain based on the user request. (`query_with_langchain.py`) -## Prerequisites: +1. The knowledge bases returns search results related to the relevant documents from the ingested data. (`query_with_langchain.py`) + +1. The app sends the user request and along with the data retrieved from the Amazon Bedrock Knowlegebases as context in the LLM prompt to a LLM available within Bedrock using Langchain. (`query_with_langchain.py`) + +1. The LLM returns a succinct response to the user request based on the retrieved data. (`query_with_langchain.py`) -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Appropriate permissions to configure Amazon Bedrock Knowledge bases. -3. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). +1. The response from the LLM is sent back to the user. (`app.py`) -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open it up in your favorite code editor.The file structure of this repo is broken into 3 key files, -the app.py file, query_with_langchain.py file and the requirements.txt. -The app.py file houses the frontend application (a streamlit app). -The query_with_langchain.py file houses the logic for taking a user question and letting the LLM generate a response, this includes both the Knowledge bases get contexts calls and Amazon Bedrock LLM API invocation using langchain. -The requirements.txt file contains all necessary dependencies for this sample application to work. +# How to use this Repo: + +## Prerequisites: -## Step 2: +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -``` -pip install virtualenv -python3.10 -m venv venv -``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -cd venv -cd bin -source activate -cd ../../ -``` +## Steps +1. Clone the repository to your local machine. -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + -``` -pip install -r requirements.txt -``` +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc + ``` -## Step 3: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -Now that we have successfully cloned the repo, created and activated the virtual environment and installed the necessary dependencies, it is time for us to create Amazon Bedrock Knowledge base. +1. Now that we have successfully cloned the repo, created and activated the virtual environment and installed the necessary dependencies, it is time for us to create Amazon Bedrock Knowledge base. To create our Amazon Bedrock Knowledge base we will: -1. Go to the Amazon Bedrock Service homepage within the AWS console and on the left-hand side we will select "Knowledge bases" under the "Orchestration" drop down ![Alt text](images/amazon_bedrock_homepage.png "Amazon Bedrock Homepage") +1. Go to the Amazon Bedrock Service homepage within the AWS console and on the left-hand side we will select "Knowledge bases" under the "Orchestration" drop down ![Alt text](images/amazon_bedrock_homepage.png "Amazon Bedrock Homepage") -2. We will then click on "Create knowledge base" ![Alt text](images/knowledgeBase_homepage.png "Amazon Bedrock Create Knowledge base") +2. We will then click on "Create knowledge base" ![Alt text](images/knowledgeBase_homepage.png "Amazon Bedrock Create Knowledge base") -3. In the Knowledge base details section, you can optionally change the default name and provide a description for your knowledge base.In the IAM permissions section, choose an AWS Identity and Access Management (IAM) role that provides Amazon Bedrock permission to access other AWS services. You can let Amazon Bedrock create the service role or choose a custom role that you have created. Optionally, add tags to your knowledge base. Select Next. ![Alt text](images/kb_first_page.png "Knowledge base details") +3. In the Knowledge base details section, you can optionally change the default name and provide a description for your knowledge base.In the IAM permissions section, choose an AWS Identity and Access Management (IAM) role that provides Amazon Bedrock permission to access other AWS services. You can let Amazon Bedrock create the service role or choose a custom role that you have created. Optionally, add tags to your knowledge base. Select Next. ![Alt text](images/kb_first_page.png "Knowledge base details") -4. On the Set up data source page, provide the information for the data source to use for the knowledge base: Optionally, change the default Data source name. Provide the S3 URI of the object containing the files for the data source that you prepared. Select Next. ![Alt text](images/kb_datasource_page.png "Set up Data Source") +4. On the Set up data source page, provide the information for the data source to use for the knowledge base: Optionally, change the default Data source name. Provide the S3 URI of the object containing the files for the data source that you prepared. Select Next. ![Alt text](images/kb_datasource_page.png "Set up Data Source") -5. In the Embeddings model section, choose a supported embeddings model to convert your data into vector embeddings for the knowledge base. In the Vector database section, choose Quick create a new vector store and select Next ![Alt text](images/kb_vectordb_page.png "Select Embeddings Model") +5. In the Embeddings model section, choose a supported embeddings model to convert your data into vector embeddings for the knowledge base. In the Vector database section, choose Quick create a new vector store and select Next ![Alt text](images/kb_vectordb_page.png "Select Embeddings Model") 6. On the Review and create page, check the configuration and details of your knowledge base. Choose Edit in any section that you need to modify. When you are satisfied, select Create knowledge base. -## Step 4: +1. create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: -Now that the requirements have been successfully installed in your virtual environment, your Bedrock Knowledge base is created, we can now begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: - -``` -profile_name= + ```zsh + profile_name= knowledge_base_id= llm_model = < LLM model that you want to use for the POC, either "amazon-titan" or "anthropic-claude > -``` + ``` -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 19 and 20 in the query_with_langchain.py file to change the region: +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 19 and 20 in the query_with_langchain.py file to change the region: -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1') + ```zsh + bedrock = boto3.client('bedrock-runtime', 'us-east-1') bedrock_agent_runtime = boto3.client('bedrock-agent-runtime','us-east-1') -``` -Since this repository is configured to leverage Amazon Titan or Anthropic Claude 3 models, the prompt payload is structured in formats required for the invocation of these two models. -If you wanted to leverage other Amazon Bedrock models, you can update query_with_langchain.py code. -For example if you to call Amazon Titan Lite instead of Amazon Titan Express, you can update call_titan funciton in query_with_langchain.py to look like this: + ``` + -```python +1. Since this repository is configured to leverage Amazon Titan or Anthropic Claude 3 models, the prompt payload is structured in formats required for the invocation of these two models. +If you wanted to leverage other Amazon Bedrock models, you can update `query_with_langchain.py` code. +For example if you to call Amazon Titan Lite instead of Amazon Titan Express, you can update call_titan funciton in `query_with_langchain.py` to look like the code below. - -def call_titan(query, retriever): +You can then change the model_id param value to the other available models from Amazon Titan. + +This repository is configured to leverage Knowledge bases. +If you want to use other Vector DBs that are not supported in Amazon Bedrock Knowledge Bases, or want to directly retreive contexts from Vector DB using langchain, you can refere to [this Langchain documentation](https://python.langchain.com/docs/modules/data_connection/retrievers/vectorstore/). + + + ```zsh + def call_titan(query, retriever): """ This function is used to call Amazon Titan Express LLM model using Langchain. :param query: Contains the Question asked by the user @@ -142,22 +136,16 @@ def call_titan(query, retriever): answer = qa(query) # Returning the response - return answer -``` - -You can then change the model_id param value to the other available models from Amazon Titan. - -This repository is configured to leverage Knowledge bases. -If you want to use other Vector DBs that are not supported in Amazon Bedrock Knowledge Bases, or want to directly retreive contexts from Vector DB using langchain, you can refere to [this Langchain documentation](https://python.langchain.com/docs/modules/data_connection/retrievers/vectorstore/). - + return answer + ``` -## Step 7: -As soon as you have successfully configured the environment variables and the required code changes, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin asking natural language questions against the data sources that you configured with Knowledge bases. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/requirements.txt index 995b80dd..eb14cd31 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-langchain-rag-poc/requirements.txt @@ -1,6 +1,8 @@ -boto3==1.34.84 -botocore==1.34.84 -python-dotenv==1.0.0 -streamlit==1.30.0 -langchain==0.1.16 -langchain-community==0.0.32 \ No newline at end of file +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +langchain-community +langchain-experimental +langchain>=0.1.0, <0.2.0 +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.projen/deps.json new file mode 100644 index 00000000..bcf95ced --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.projen/deps.json @@ -0,0 +1,30 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "requests", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/README.md index 3220375e..10830e7b 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/README.md @@ -1,95 +1,101 @@ -# Amazon-Bedrock-meeting-minutes-summarization +# Amazon Bedrock Meeting Minutes Summarization POC + +## Overview of Solution This application demonstrates using Amazon Bedrock and Amazon Transcribe to summarize meeting recordings. The streamlit frontend allows users to upload audio, video, or text files of meeting recording. Amazon Transcribe generates a transcript of recording and sent it Amazon Bedrock for summarization of the key discussion points. Users can then download the generated summarized meeting notes. -![Alt text](images/demo.gif) +![A gif of a screen recording show casing the Amazon Bedrock Meeting Minutes Summarization POC functionality](images/demo.gif) -# **Goal of this Repo:** +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock and Amazon Transcribe to create Meeting minutes from audio ,video recordings. If audio It show case the capablitiy to upload Audio, Video of meeting recording and create summary of meeting. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/architecture.PNG "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: +When a user interacts with the POC, the flow is as follows: 1. The user uploads a meeting recording video or audio or .txt file using Upload File button. -2. Meeting recording is already present in Amazon Transcribe Job History Transcription text is retrieved from Job History -3. If Meeting recording is not present in Amazon Transcribe Job history, recording file is temporary upload on S3 and Sent to Amazon Transcribe Job to generate transcription text -4. Transcription text is sent to Amazon Bedrock LLM for summarization -5. Summarization notes are updated in streamlit app -6. User can download the meeting notes +1. Meeting recording is already present in Amazon Transcribe Job History Transcription text is retrieved from Job History -# How to use this Repo: +1. If Meeting recording is not present in Amazon Transcribe Job history, recording file is temporary upload on S3 and Sent to Amazon Transcribe Job to generate transcription text -## Prerequisites: +1. Transcription text is sent to Amazon Bedrock LLM for summarization + +1. Summarization notes are updated in streamlit app + +1. User can download the meeting notes -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Amazon Transcribe Access -3. S3 Bucket with permissions to upload/delete objects. This is require to upload the Transcriptions. -4. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` +# How to use this Repo: + +## Prerequisites: + +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -After cloning the repo onto your local machine, open it up in your favorite code editor. -## Step 2: -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: +1. Access to Amazon Transcribe via your CLI Credentials -``` -pip install virtualenv -python3.10 -m venv venv -``` +1. Access to S3 Bucket with put,get,delete object permissions via your CLI credentials and accessible by Transcribe -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -cd venv -cd bin -source activate -cd ../../ -``` +## Steps +1. Clone the repository to your local machine. -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `llm.py` - This file has the logic to interact with LLM using Amazon Bedrock API. + + * `transcribe_util.py` - This is the file that contains the logic to interact with Amazon Transcribe like starting Transcribe Job, getting Transcription job history, getting transcription text. + + * `s3_util.py` - This is the file that contains the logic to interact with S3 bucket. + + -``` -pip install -r requirements.txt -``` +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc + ``` -## Step 3: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -Now that the requirements have been successfully installed in your virtual environment we can configure S3 Bucket required for temporary uploading the file +1. Configure S3 Bucket required for temporary uploading the file Update the S3 Bucket name with your bucket name in **line 21** **app.py** : -``` -S3_BUCKET_NAME = "" -``` + ```zsh + S3_BUCKET_NAME = "" + ``` -## Step 4: **Running the UI** -``` -streamlit run app.py -``` -# POC Environment -This section will walk you through the various files that exist in this POC directory. +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -* `app.py` - This the main application that generates the UI through streamlit. -* `llm.py` - This file has the logic to interact with LLM using Amazon Bedrock API. -* `transcribe_util.py` - This is the file that contains the logic to interact with Amazon Transcribe like starting Transcribe Job, getting Transcription job history, getting transcription text. -* `s3_util.py` - This is the file that contains the logic to interact with S3 bucket. -* `requirements.txt` - The python packages required for the app to function. You will reference this during setup - +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) diff --git a/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/requirements.txt index c445187c..b46111b1 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-meeting-minutes-summarization-poc/requirements.txt @@ -1,4 +1,6 @@ -boto3==1.34.41 -botocore==1.34.41 -requests==2.31.0 -streamlit==1.31.1 \ No newline at end of file +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +requests +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.gitattributes new file mode 100644 index 00000000..1688f42a --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.gitattributes @@ -0,0 +1,11 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.gitignore new file mode 100644 index 00000000..3f778d7d --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.gitignore @@ -0,0 +1,84 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.projen/files.json new file mode 100644 index 00000000..75ce256b --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.projen/files.json @@ -0,0 +1,12 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-customization/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-customization/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-customization/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/requirements.txt new file mode 100644 index 00000000..c0c70d83 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-customization/requirements.txt @@ -0,0 +1,5 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.projen/deps.json new file mode 100644 index 00000000..2ac08bbe --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.projen/deps.json @@ -0,0 +1,34 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "bs4", + "type": "runtime" + }, + { + "name": "pandas", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/HOWTO.md new file mode 100644 index 00000000..2bc8b0b6 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/HOWTO.md @@ -0,0 +1,33 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + + +## Question & Answer (Q&A) +The Question & Answer (Q&A) model evaluation prep builds a prompt that includes the question and possible answer choices. For the Q&A workflow, you will be asked to map the following CSV columns. You will need to map the following columns: +* Question ID - The unique ID for each question. +* Question - The quetion text +* Answer - The answer value to the question +* Is Correct - If the answer in is correct or incorrect +* Category - The question category (Optional) + +At this time, data mapping for Q&A requires each answer to have a row. Answers are grouped by Question by using the question ID. + +## Text Summarization +The text summarization model evaluation prep builds a prompt that includes the CSV columns you select and is instructed to summarize the provided content. + +Additionally, you will need to map the Expected Answer, which is what you expect the Bedrock Model to respond with as a summary. This is used to evaluate the quality of output compared to your expectations. Category can also be mapped, but is not required. + +## Classification +The classification model evaluation prep builds a prompt that includes the CSV columns you select and is instructed to respond with a classification category from a list of provided categories. + +Additionally, you will need to map the Expected Answer, which is what you expect the Bedrock Model to respond with as a classification category. +You will be prompted to provide a comma seperated list of classification categories that you'd like to the model to use when determining what classification category should assigned as the response. Category can also be mapped, but is not required, and doesn't impact the classification category determination. + + +## Text Generation +The text generation model evalution prep builds a prompt that includes the CSV columns you select and is instructed to generate text using the provided text. + +Additionally, you will need to map the Expected Answer, which is what you expect the Bedrock Model to respond with as Generated Text. Category can also be mapped, but is not required. \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/README.md index e34ed737..9d2982ed 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/README.md @@ -1,100 +1,82 @@ -# Amazon-Bedrock-Model-Eval-POC +# Amazon Bedrock Model Evaluation Data Prep Tool + +## Overview of Solution This is sample code aimed to accelerate customers aiming to leverage [Amazon Bedrock Model Evaluator](https://docs.aws.amazon.com/bedrock/latest/userguide/model-evaluation.html) with custom prompt data. This Proof-of-Concept (POC) enables users to provide a CSV containing data that should be used with Amazon Bedrock Model Evaluator. The user then maps the CSV columns to the appropriate fields depending on which type of Model Evaluation being executed. This will generate one or more `.jsonl` formatted files, ready for use with Amazon Bedrock Model Evaluator. -![Demo of the Amazon Bedrock Model Eval POC](images/demo.gif) +![A gif of a screen recording show casing the Amazon Bedrock Model Evaluation Data Prep Tool functionality](images/demo.gif) + + +## Goal of this POC +The goal of this POC is to help customers understand how to transform data from CSV format to an Amazon Bedrock Model Evaluation dataset. + + +When a user interacts with the POC, the flow is as follows: + +1. Run the POC (see "How to use this Repo") -## At a glance -At a high-level, the POC workflow is: -1. Run the POC (see "How to use this Repo") 1. Upload CSV of data to use with Model Evaluator + 1. Select the type of Model Evaluation being performed + 1. Map CSV columns to expected fields specific to the prompt type selected + 1. Download generated `.jsonl` file(s) + 1. Upload the generated `.jsonl` files to an Amazon S3 bucket that Amazon Bedrock Model Evalutor can access + 1. Execute Model Evaluation using custom prompts pointing to the newly uploaded prompt dataset. If you have more than 1,000 prompts, multiple files will have been generated. You can only execute model evaluation on a maximum of 1,000 records. - # How to use this Repo: - ## Prerequisites: - 1. Amazon Bedrock Access and CLI Credentials. Ensure the AWS credentials have access to execute Amazon Bedrock Model Evaluation. - 2. Ensure Python 3.11 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). - 3. Ensure you have access to an Amazon S3 bucket where you can upload generated data. Amazon Bedrock Model Evaluator will also need access to read and write to this bucket during Model Evaluation. - ## Step 1: +# How to use this Repo: - The first step of utilizing this repo is performing a git clone of the repository. +## Prerequisites: - ``` - git clone https://github.com/aws-samples/genai-quickstart-pocs.git - ``` - After cloning the repo onto your local machine, open the repo in your favorite code editor. Navigate to this POC folder within the repo. +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. - The POC consists of two files: - * `app.py` is the frontend application that is run using streamlit - * `logic.py` is the logic that processes the data from the front-end +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. - ## Step 2: - Set up a python virtual environment in the directory of the POC and ensure that you are using Python 3.11. This can be done by running the following commands: (make sure you've set your working directory in terminal to the POC directory) +1. Ensure you have access to an Amazon S3 bucket where you can upload generated data. Amazon Bedrock Model Evaluator will also need access to read and write to this bucket during Model Evaluation. - ```zsh - pip install virtualenv - python3.11 -m venv venv + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git ``` - The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). - After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `logic.py` - the logic that processes the data from the front-end + + + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: ```zsh - source venv/bin/activate + cd genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc ``` - After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: - +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* ```zsh + python -m venv .env + source .env/bin/activate pip install -r requirements.txt ``` - ## Step 4: - Your machine should now be configured to run the POC. To start the POC, execute the following from the command line (from the POC directory, with the virtual environment activated): - +1. Start the POC from your terminal ```zsh streamlit run app.py ``` - This should start the POC and open a browser window to the application. Follow the instructions in the application to generate prompt data. - -# Using the Model Evaluator Data Prep tool -Once the streamlit app is up and running in your browser, it's time to complete the form in the tool with the correct details from your data. - -There are four evaluation types: **Question & Answer (Q&A)**, **Text Generation**, **Text Summarization**, and **Classification**. Depending on your data and goals, you may be able to execute different evaluations on the same data using the tool to prep the data for each evaluation type. - -*Currently, CSV data requires column headers. **Please make sure your data includes headers in your CSV file before starting with the tool.*** - -Once you complete the fields in the tool, it will generate `.jsonl` files for use with Amazon Bedrock Model Evaluator. Download the `.jsonl` files and follow the [guidance]((https://docs.aws.amazon.com/bedrock/latest/userguide/model-evaluation.html)) from Amazon Bedrock Model Evaluator to start evaluating models with your custom prompts. - -## Question & Answer (Q&A) -The Question & Answer (Q&A) model evaluation prep builds a prompt that includes the question and possible answer choices. For the Q&A workflow, you will be asked to map the following CSV columns. You will need to map the following columns: -* Question ID - The unique ID for each question. -* Question - The quetion text -* Answer - The answer value to the question -* Is Correct - If the answer in is correct or incorrect -* Category - The question category (Optional) - -At this time, data mapping for Q&A requires each answer to have a row. Answers are grouped by Question by using the question ID. - -## Text Summarization -The text summarization model evaluation prep builds a prompt that includes the CSV columns you select and is instructed to summarize the provided content. - -Additionally, you will need to map the Expected Answer, which is what you expect the Bedrock Model to respond with as a summary. This is used to evaluate the quality of output compared to your expectations. Category can also be mapped, but is not required. - -## Classification -The classification model evaluation prep builds a prompt that includes the CSV columns you select and is instructed to respond with a classification category from a list of provided categories. - -Additionally, you will need to map the Expected Answer, which is what you expect the Bedrock Model to respond with as a classification category. -You will be prompted to provide a comma seperated list of classification categories that you'd like to the model to use when determining what classification category should assigned as the response. Category can also be mapped, but is not required, and doesn't impact the classification category determination. - +This should start the POC and open a browser window to the application. -## Text Generation -The text generation model evalution prep builds a prompt that includes the CSV columns you select and is instructed to generate text using the provided text. +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -Additionally, you will need to map the Expected Answer, which is what you expect the Bedrock Model to respond with as Generated Text. Category can also be mapped, but is not required. \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/requirements.txt index 51e96677..40067bf3 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-eval-poc/requirements.txt @@ -1,3 +1,7 @@ -bs4==0.0.2 -streamlit==1.31.1 -pandas==2.2.0 \ No newline at end of file +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +bs4 +pandas +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/README.md index 8d0bba2e..095b1fbe 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/README.md @@ -1,88 +1,86 @@ -# Amazon-Bedrock-Model-Playground-POC +# Amazon Bedrock Model Playground POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a Gen AI model playground. The application is constructed with a simple streamlit frontend where users can input zero shot requests and select any LLM offered by Amazon Bedrock. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Model Playground POC functionality](images/demo.gif) + +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock and select any of the available Amazon Bedrock LLMs to ask zero shot requests. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: +When a user interacts with the POC, the flow is as follows: -1. The user selects the Amazon Bedrock Model they want to use and makes a "zero-shot" request to the streamlit frontend. (app.py). -2. The application takes the question and the model chosen and routes it to the appropriate model (model_invoker.py). All specific model invocations are stored in (model_selector.py). -3. The final answer is generated by the Amazon Bedrock Model chosen and displayed on the frontend application (app.py). +1. The user selects the Amazon Bedrock Model they want to use and makes a "zero-shot" request to the streamlit frontend. (`app.py`). -# How to use this Repo: +1. The application takes the question and the model chosen and routes it to the appropriate model (`model_invoker.py`). All specific model invocations are stored in (model_selector.py). -## Prerequisites: +1. The final answer is generated by the Amazon Bedrock Model chosen and displayed on the frontend application (`app.py`). -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3100/). -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` +# How to use this Repo: -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 4 key files, -the app.py file, the model_invoker.py file, the model_selector.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The model_invoker.py file houses the simple logic of the application to help orchestrate which model should be invoked based on the users selection. -The model_selector.py houses the logic required to invoke the specific model chosen by the end user and generate the final response. -The requirements.txt file contains all necessary dependencies for this sample application to work. +## Prerequisites: -## Step 2: +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.10. This can be done by running the following commands: +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -``` -pip install virtualenv -python3.10 -m venv venv -``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -cd venv -cd bin -source activate -cd ../../ -``` +## Steps +1. Clone the repository to your local machine. -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `model_invoker.py` - This file has the logic to interact with LLM using Amazon Bedrock API. + + * `model_selector.py` - This is the file that contains the logic to map the model selected by the user to the appropriate Amazon Bedrock Model. + + -``` -pip install -r requirements.txt -``` +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc + ``` -## Step 3: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this POC specific directory within this repo. Within the .env file you just created you will need to configure the .env to contain: +1. reate a .env file in the root of this POC specific directory within this repo. Within the .env file you just created you will need to configure the .env to contain: -``` -profile_name= + ```zsh + profile_name= region_name=us-east-1 (region of choice) -``` - -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! + ``` -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin asking zero-shot questions against any Amazon Bedrock model of your choice. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/requirements.txt index df79a1bb..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-model-playground-poc/requirements.txt @@ -1,48 +1,5 @@ -altair==5.3.0 -attrs==23.2.0 -blinker==1.7.0 -boto3==1.34.88 -botocore==1.34.88 -cachetools==5.3.3 -certifi==2024.2.2 -charset-normalizer==3.3.2 -click==8.1.7 -gitdb==4.0.11 -GitPython==3.1.43 -idna==3.7 -Jinja2==3.1.3 -jmespath==1.0.1 -jsonschema==4.21.1 -jsonschema-specifications==2023.12.1 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -mdurl==0.1.2 -numpy==1.26.4 -packaging==24.0 -pandas==2.2.2 -pillow==10.3.0 -pip==23.2.1 -protobuf==4.25.3 -pyarrow==16.0.0 -pydeck==0.8.1b0 -Pygments==2.17.2 -python-dateutil==2.9.0.post0 -python-dotenv==1.0.1 -pytz==2024.1 -referencing==0.34.0 -requests==2.31.0 -rich==13.7.1 -rpds-py==0.18.0 -s3transfer==0.10.1 -setuptools==68.2.0 -six==1.16.0 -smmap==5.0.1 -streamlit==1.33.0 -tenacity==8.2.3 -toml==0.10.2 -toolz==0.12.1 -tornado==6.4 -typing_extensions==4.11.0 -tzdata==2024.1 -urllib3==2.2.1 -wheel==0.41.2 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.projen/deps.json new file mode 100644 index 00000000..ed1641a1 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.projen/deps.json @@ -0,0 +1,59 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "docx2txt", + "type": "runtime" + }, + { + "name": "langchain-aws", + "type": "runtime" + }, + { + "name": "langchain-community", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.3", + "type": "runtime" + }, + { + "name": "pypdf", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "python-pptx", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "uuid", + "type": "runtime" + }, + { + "name": "wikipedia", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/README.md index f59dc3e3..f624991d 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/README.md @@ -1,11 +1,16 @@ -# Amazon Bedrock PowerPoint Generator POC +# Amazon Bedrock PowerPoint Generator ## Overview of Solution This is sample code demonstrates the use of Amazon Bedrock and Generative AI to implement a PowerPoint generator. The application is constructed with a simple streamlit frontend where users can input a topic and get a PowerPoint generated based on the topic. Using Generative AI, the solution creates relevant Wikipedia queries to perform in-depth research on the presentation content. -![A gif of a screen recording show casing the Amazon Bedrock PowerPoint Generator POC functionality](images/demo.gif) -*Note: Screen recording playback speed is faster than how it actually functions.* +![A gif of a screen recording show casing the Amazon Bedrock PowerPoint Generator functionality](images/demo.gif) + + +## Goal of this POC +The goal of this POC is to showcase leveraging Generative AI for to create both the content for a presentation and also the background research queries to support the content generation. + + # How to use this Repo: @@ -45,4 +50,5 @@ This is sample code demonstrates the use of Amazon Bedrock and Generative AI to This should start the POC and open a browser window to the application. ## How-To Guide -For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) \ No newline at end of file +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) + diff --git a/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/requirements.txt index f9e34cec..84974c4c 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-powerpoint-generator-poc/requirements.txt @@ -1,12 +1,13 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". boto3 botocore +docx2txt langchain-aws langchain-community langchain>=0.3.0, <0.4.0 +pypdf python-dotenv python-pptx streamlit uuid wikipedia -pypdf -docx2txt \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/README.md index 0525a4a4..8a04dde3 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/README.md @@ -1,183 +1,120 @@ -# Amazon-Bedrock-RAG-Kendra-POC +# Amazon Bedrock RAG with Kendra POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a RAG based architecture with Amazon Kendra. The application is constructed with a simple streamlit frontend where users can ask questions against documents stored in Amazon Kendra. -![Alt text](images/demo.gif) +![A gif of a screen recording show casing the Amazon Bedrock RAG with Kendra POC functionality](images/demo.gif) -# **Goal of this Repo:** +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to take natural language questions, and answer questions against indexed documents in Amazon Kendra. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') + + +When a user interacts with the POC, the flow is as follows: + +1. The user makes a request to the GenAI app (`app.py`). + +1. The app issues a search query to the Amazon Kendra index based on the user request. (`kendra_bedrock_query.py`) + +1. The index returns search results with excerpts of relevant documents from the ingested data. (`kendra_bedrock_query.py`) + +1. The app sends the user request and along with the data retrieved from the index as context in the LLM prompt. (`kendra_bedrock_query.py`) + +1. The LLM returns a succinct response to the user request based on the retrieved data. (`kendra_bedrock_query.py`) + +1. The response from the LLM is sent back to the user. (app.py) -![Alt text](images/kendra-rag-architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: -1. The user makes a request to the GenAI app (app.py). -2. The app issues a search query to the Amazon Kendra index based on the user request. (kendra_bedrock_query.py) -3. The index returns search results with excerpts of relevant documents from the ingested data. (kendra_bedrock_query.py) -4. The app sends the user request and along with the data retrieved from the index as context in the LLM prompt. (kendra_bedrock_query.py) -5. The LLM returns a succinct response to the user request based on the retrieved data. (kendra_bedrock_query.py) -6. The response from the LLM is sent back to the user. (app.py) # How to use this Repo: ## Prerequisites: -1. Amazon Kendra Index has been created (IF NOT ALREADY CREATED it is covered in step 3). -2. Amazon Kendra Index has a datasource configured and synced (IF NOT ALREADY CREATED it is covered in step 4). -3. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -4. Appropriate permissions to configure Amazon Kendra Index and Amazon Kendra Data Sources. -5. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. +1. Access to create and configure Amazon Kendra Indexes -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open it up in your favorite code editor.The file structure of this repo is broken into 3 key files, -the app.py file, the kendra_bedrock_query.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The kendra_bedrock_query.py file houses the logic of the application, including the Kendra Retrieve API calls and Amazon Bedrock API invocations. -The requirements.txt file contains all necessary dependencies for this sample application to work. +## Steps +1. Clone the repository to your local machine. -## Step 2: + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `kendra_bedrock_query` - The logic of the application, including the Kendra Retrieve API calls and Amazon Bedrock API invocations. + + -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc + ``` -``` -pip install virtualenv -python3.10 -m venv venv -``` +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: +1. **Create your Amazon Kendra Index (if you don't already have one)** + 1. Go to Amazon Kendra in your AWS Console and click on "Create an Index" ![Alt text](images/Amazon_kendra_homepage.png "Kendra Homepage") + 2. Fill out the "Specify Index details" page, and provide Kendra a role that can access CloudWatch Logs. ![Alt text](images/kendra_specify_index_details.png "Kendra Specify Details Page") + 3. Fill out the "Configure Access Control" page ![Alt text](images/kendra_access_control.png "Kendra Access Control") + 4. Select the appropriate provisioning editions and create ![Alt text](images/specify_provisioning_kendra.png "Kendra Edition Selection") + 5. You can find your Kendra Index ID in the console as seen in the screenshot: ![Alt text](images/kendra_screen_shot.png "Kendra Index") -``` -cd venv -cd bin -source activate -cd ../../ -``` -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: +1. Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: -``` -pip install -r requirements.txt -``` + ```zsh + profile_name= +kendra_index= + ``` -## Step 3: -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 11 in the kendra_bedrock_query.py file to change the region: -``` -profile_name= -kendra_index= -``` - -Please ensure that your AWS CLI Profile has access to Amazon Bedrock, and your Amazon Kendra Index has been created within your AWS account! - -**_If you don't have your Amazon Kendra Index created yet, please follow the steps below:_** - -1. Go to Amazon Kendra in your AWS Console and click on "Create an Index" ![Alt text](images/Amazon_kendra_homepage.png "Kendra Homepage") -2. Fill out the "Specify Index details" page, and provide Kendra a role that can access CloudWatch Logs. ![Alt text](images/kendra_specify_index_details.png "Kendra Specify Details Page") -3. Fill out the "Configure Access Control" page ![Alt text](images/kendra_access_control.png "Kendra Access Control") -4. Select the appropriate provisioning editions and create ![Alt text](images/specify_provisioning_kendra.png "Kendra Edition Selection") -5. You can find your Kendra Index ID in the console as seen in the screenshot: ![Alt text](images/kendra_screen_shot.png "Kendra Index") - -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 11 in the kendra_bedrock_query.py file to change the region: - -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock.us-east-1.amazonaws.com') -``` - -Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the invokeLLM() function in the kendra_bedrock_query.py to look like: - -```python -def invokeLLM(question, kendra_response): - """ - This function takes in the question from the user, along with the Kendra responses as context to generate an answer - for the user on the frontend. - :param question: The question the user is asking that was asked via the frontend input text box. - :param kendra_response: The response from the Kendra document retrieve query, used as context to generate a better - answer. - :return: Returns the final answer that will be provided to the end-user of the application who asked the original - question. - """ - # Setup Bedrock client - bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') - # configure model specifics such as specific model - modelId = 'anthropic.claude-v2' - accept = 'application/json' - contentType = 'application/json' - # prompt that is passed into the LLM with the Kendra Retrieval context and question - # TODO: FEEL FREE TO EDIT THIS PROMPT TO CATER TO YOUR USE CASE - prompt_data = f"""\n\nHuman: -Answer the following question to the best of your ability based on the context provided. -Provide an answer and provide sources and the source link to where the relevant information can be found. Include this at the end of the response -Do not include information that is not relevant to the question. -Only provide information based on the context provided, and do not make assumptions -Only Provide the source if relevant information came from that source in your answer -Use the provided examples as reference -### -Question: {question} - -Context: {kendra_response} - -### - -\n\nAssistant: - -""" - # body of data with parameters that is passed into the bedrock invoke model request - # TODO: TUNE THESE PARAMETERS AS YOU SEE FIT - body = json.dumps({"prompt": prompt_data, - "max_tokens_to_sample": 8191, - "temperature": 0, - "top_k": 250, - "top_p": 0.5, - "stop_sequences": [] - }) - # Invoking the bedrock model with your specifications - response = bedrock.invoke_model(body=body, - modelId=modelId, - accept=accept, - contentType=contentType) - # the body of the response that was generated - response_body = json.loads(response.get('body').read()) - # retrieving the specific completion field, where you answer will be - answer = response_body.get('completion') - # returning the answer as a final result, which ultimately gets returned to the end user - return answer -``` - -You can then change the modelId variable to the model of your choice. - -## Step 4: - -Now that you have cloned the repo, created a virtual environment, set the environment variables, and provisioned your Kendra index, it is now time -to sync a data source within Kendra. As seen in the screenshot below, you can configure the specific datasource that you would like to sync. For more information + ```zsh + bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock.us-east-1.amazonaws.com') + ``` + + +1. Time to sync a data source within Kendra. As seen in the screenshot below, you can configure the specific datasource that you would like to sync. For more information on data sources feel free to refer to this [documentation](https://docs.aws.amazon.com/kendra/latest/dg/hiw-data-source.html). -![Alt text](images/kendra_data_source.png "Kendra Data Source") +![Alt text](images/kendra_data_source.png "Kendra Data Source") + +**_If you don't have your own sample data, or sample data source you can leverage the sample datasource within Amazon Kendra data sources as shown below:_** -**_If you don't have your own sample data, or sample data source you can leverage the sample datasource within Amazon Kendra data sources as shown below:_** + 1. On the data sources tab, click on the add dataset option as seen in the image: ![Alt text](images/sample_data_sources.png "Kendra Sample Data Source") + 2. Then define the data sources attributes such as the data source name and click add data source: ![Alt text](images/sample_data_source_configuration.png "Kendra Sample Data Source Config") + 3. This will automatically create the data source and triggers a sync. You will now be able to ask questions against Sample AWS Documentation that covers Kendra, EC2, S3 and Lambda in your front end application. -1. On the data sources tab, click on the add dataset option as seen in the image: ![Alt text](images/sample_data_sources.png "Kendra Sample Data Source") -2. Then define the data sources attributes such as the data source name and click add data source: ![Alt text](images/sample_data_source_configuration.png "Kendra Sample Data Source Config") -3. This will automatically create the data source and triggers a sync. You will now be able to ask questions against Sample AWS Documentation that covers Kendra, EC2, S3 and Lambda in your front end application. -## Step 5: -As soon as you have successfully synced your data source with your Kendra Index, your application should be ready to go. To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin asking natural language questions against the documents stored within your Amazon Kendra index. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/images/kendra-rag-architecture.png b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/images/architecture.png similarity index 100% rename from genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/images/kendra-rag-architecture.png rename to genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/images/architecture.png diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/requirements.txt index 6f473640..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-kendra-poc/requirements.txt @@ -1,58 +1,5 @@ -altair==5.1.1 -attrs==23.1.0 -awscli==1.29.59 -blinker==1.6.2 -boto3==1.28.59 -botocore==1.31.59 -cachetools==5.3.1 -certifi==2023.7.22 -charset-normalizer==3.2.0 -click==8.1.7 -colorama==0.4.4 -docutils==0.16 -gitdb==4.0.10 -GitPython==3.1.41 -idna==3.4 -importlib-metadata==6.8.0 -Jinja2==3.1.3 -jmespath==1.0.1 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -mdurl==0.1.2 -numpy==1.26.0 -packaging==23.1 -pandas==2.1.1 -Pillow==10.2.0 -pip==23.3 -protobuf==4.24.3 -pyarrow==14.0.1 -pyasn1==0.5.0 -pydeck==0.8.1b0 -Pygments==2.16.1 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -PyYAML==6.0.1 -referencing==0.30.2 -requests==2.31.0 -rich==13.5.3 -rpds-py==0.10.3 -rsa==4.7.2 -s3transfer==0.7.0 -setuptools==65.5.1 -six==1.16.0 -smmap==5.0.1 -streamlit==1.30.0 -tenacity==8.2.3 -toml==0.10.2 -toolz==0.12.0 -tornado==6.3.3 -typing_extensions==4.8.0 -tzdata==2023.3 -tzlocal==5.0.1 -urllib3==1.26.18 -validators==0.22.0 -wheel==0.38.4 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.projen/deps.json new file mode 100644 index 00000000..d93887bd --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.projen/deps.json @@ -0,0 +1,43 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "langchain-community", + "type": "runtime" + }, + { + "name": "langchain-experimental", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.1", + "type": "runtime" + }, + { + "name": "opensearch-py", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/README.md index de1bfccb..579810b7 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/README.md @@ -1,232 +1,137 @@ -# Amazon-Bedrock-RAG-OpenSearchServerless-POC +# Amazon Bedrock RAG with OpenSearch Serverless POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to create custom embeddings stored in Amazon OpenSearch Serverless with the ability ask questions against the stored documents. The application is constructed with a RAG based architecture where users can ask questions against the indexed embeddings within OpenSearch Serverless. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock RAG with OpenSearch Serverless POC functionality](images/demo.gif) + +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to take natural language questions, and answer questions against embedded and indexed documents in Amazon OpenSearch Serverless Vector Search. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/gen_ai_opensearch.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: +When a user interacts with the POC, the flow is as follows: -1. The user makes a request to the GenAI app (app.py). -2. The app issues a k-nearest-neighbors search query to the Amazon OpenSearch Serverless Vector Search index based on the user request. (query_against_opensearch.py) -3. The index returns search results with excerpts of relevant documents from the ingested data. (query_against_opensearch.py) -4. The app sends the user request and along with the data retrieved from the Amazon OpenSearch Serverless Vector Search index as context in the LLM prompt. (query_against_opensearch.py) -5. The LLM returns a succinct response to the user request based on the retrieved data. (query_against_opensearch.py) -6. The response from the LLM is sent back to the user. (app.py) +1. The user makes a request to the GenAI app (`app.py`) -# How to use this Repo: +1. The app issues a k-nearest-neighbors search query to the Amazon OpenSearch Serverless Vector Search index based on the user request. (`query_against_opensearch.py`) -## Prerequisites: +1. The index returns search results with excerpts of relevant documents from the ingested data. (`query_against_opensearch.py`) + +1. The app sends the user request and along with the data retrieved from the Amazon OpenSearch Serverless Vector Search index as context in the LLM prompt. (`query_against_opensearch.py`) -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Appropriate permissions to configure Amazon OpenSearch Serverless Vector Search. -3. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). +1. The LLM returns a succinct response to the user request based on the retrieved data. (`query_against_opensearch.py`) -## Step 1: +1. The response from the LLM is sent back to the user. (`app.py`) -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -After cloning the repo onto your local machine, open it up in your favorite code editor.The file structure of this repo is broken into 4 key files, -the app.py file, the docs_to_openSearch.py file, the query_against_openSearch.py file and the requirements.txt. -The app.py file houses the frontend application (a streamlit app). -The docs_to_openSearch.py file houses the logic needed to take a PDF document stored on your local machine, creating the embeddings and storing it in your OpenSearch Index. -The query_against_openSearch.py file houses the logic for taking a user question and letting the LLM generate a response, this includes both the OpenSearch Query API calls and Amazon Bedrock API invocation. -The requirements.txt file contains all necessary dependencies for this sample application to work. -## Step 2: +# How to use this Repo: + +## Prerequisites: + +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: -``` -pip install virtualenv -python3.10 -m venv venv -``` +1. Access to create and configure Amazon OpenSearch Serverless collections -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -cd venv -cd bin -source activate -cd ../../ -``` +## Steps +1. Clone the repository to your local machine. -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `docs_to_openSearch.py` - the logic needed to take a PDF document stored on your local machine, creating the embeddings and storing it in your OpenSearch Index. + + * `query_against_opensearch.py` - The logic of the application, including the Amazon OpenSearch Serverless Vector Search calls and Amazon Bedrock API invocations. + + -``` -pip install -r requirements.txt -``` +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc + ``` -## Step 3: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -Now that we have successfully cloned the repo, created and activated the virtual environment and installed the necessary dependencies, it is time for us to create our Amazon OpenSearch Serverless -Vector Search collection. +1. Create the Amazon OpenSearch Serverless Vector Search collection. -To create our Amazon OpenSearch Vector Search Collection we will: + To create our Amazon OpenSearch Vector Search Collection we will: -1. Go to the Amazon OpenSearch Service homepage within the AWS console and on the left-hand side we will select "Collections" under the "Serverless" drop down ![Alt text](images/Amazon_OpenSearch_Homepage.png "Amazon OpenSearch Serverless Homepage") -2. We will then click on "Create collection" ![Alt text](images/create_collection.png "Amazon OpenSearch Create Collection") -3. On the "Configure collection settings" page, we will need to input a "Collection name", select the "Collection type": "Vector search", in the "Security" section select the option "Standard create", and select your preferred "Encryption" settings: ![Alt text](images/Configure_collection_settings_part_1.png "Amazon OpenSearch Serverless Collection Settings Part-1") -4. On the same "Configure collection settings" page, at the bottom we will select our "Network access settings" either "Public" or "VPC", and give access to the OpenSearch Endpoint and/or OpenSearch Dashboards and select next ![Alt text](images/configure_collection_settings_part_2.png "Amazon OpenSearch Create Collection Part 2") -5. On the "Configure data access" page we must input a "Rule name", add the user for which you have CLI credentials for, and for the sake of the POC Grant all permissions and select Next ![Alt text](images/configure_data_access.png "Amazon OpenSearch Configure Data Access") -6. We will then enter an access policy name and select Next ![Alt text](images/access_policy_definition.png "Amazon OpenSearch Configure Data Access Part 2") -7. We will confirm all of our configuration items, and press Submit ![Alt text](images/collection_create_confirm.png "Amazon OpenSearch Collection Confirm") -8. As soon as the collection is created, you will want to **BE SURE TO NOTE DOWN THE OPENSEARCH ENDPOINT** ![Alt text](images/OpenSearch-endpoint.png "Amazon OpenSearch Endpoint") + 1. Go to the Amazon OpenSearch Service homepage within the AWS console and on the left-hand side we will select "Collections" under the "Serverless" drop down ![Alt text](images/Amazon_OpenSearch_Homepage.png "Amazon OpenSearch Serverless Homepage") + 2. We will then click on "Create collection" ![Alt text](images/create_collection.png "Amazon OpenSearch Create Collection") + 3. On the "Configure collection settings" page, we will need to input a "Collection name", select the "Collection type": "Vector search", in the "Security" section select the option "Standard create", and select your preferred "Encryption" settings: ![Alt text](images/Configure_collection_settings_part_1.png "Amazon OpenSearch Serverless Collection Settings Part-1") + 4. On the same "Configure collection settings" page, at the bottom we will select our "Network access settings" either "Public" or "VPC", and give access to the OpenSearch Endpoint and/or OpenSearch Dashboards and select next ![Alt text](images/configure_collection_settings_part_2.png "Amazon OpenSearch Create Collection Part 2") + 5. On the "Configure data access" page we must input a "Rule name", add the user for which you have CLI credentials for, and for the sake of the POC Grant all permissions and select Next ![Alt text](images/configure_data_access.png "Amazon OpenSearch Configure Data Access") + 6. We will then enter an access policy name and select Next ![Alt text](images/access_policy_definition.png "Amazon OpenSearch Configure Data Access Part 2") + 7. We will confirm all of our configuration items, and press Submit ![Alt text](images/collection_create_confirm.png "Amazon OpenSearch Collection Confirm") + 8. As soon as the collection is created, you will want to **BE SURE TO NOTE DOWN THE OPENSEARCH ENDPOINT** ![Alt text](images/OpenSearch-endpoint.png "Amazon OpenSearch Endpoint") -## Step 4: -With our Amazon OpenSearch Serverless Vector Search collection created, we now must create our Vector Index. As soon as this is created we will begin indexing our PDF document. +1. With our Amazon OpenSearch Serverless Vector Search collection created, we now must create our Vector Index. As soon as this is created we will begin indexing our PDF document. -1. Within the OpenSearch Serverless Collection we just created, we will select "Create vector index" ![Alt text](images/create_vector_index.png "Create Vector Index") -2. We will then input a Vector Index Name, Vector Field Name, Dimensions and distance metric... **BE SURE TO NOTE DOWN THE VECTOR INDEX NAME AND VECTOR FIELD NAME**. The Dimensions field is expecting an integer, in our case since we are using the 'amazon.titan-embed-text-v1' embeddings model, the dimension size will be 1536. If you plan on using a different embeddings model you will need to change this value to represent the output vector size of that specific model. Then Select "Create" ![Alt text](images/create_vector_index_name.png "Create Vector Index Details") ![Alt text](images/vector_field.png "Create Vector Index Details") -3. **_OPTIONAL:_** If you want to add meta-data to your documents that you plan on indexing, you must specify those fields in this vector index configuration. If you plan on adding meta-data you will need to reconfigure some of the code in the docs_to_openSearch.py file ![Alt text](images/metadata.png "Add Meta-Data") + 1. Within the OpenSearch Serverless Collection we just created, we will select "Create vector index" ![Alt text](images/create_vector_index.png "Create Vector Index") + 2. We will then input a Vector Index Name, Vector Field Name, Dimensions and distance metric... **BE SURE TO NOTE DOWN THE VECTOR INDEX NAME AND VECTOR FIELD NAME**. The Dimensions field is expecting an integer, in our case since we are using the 'amazon.titan-embed-text-v1' embeddings model, the dimension size will be 1536. If you plan on using a different embeddings model you will need to change this value to represent the output vector size of that specific model. Then Select "Create" ![Alt text](images/create_vector_index_name.png "Create Vector Index Details") ![Alt text](images/vector_field.png "Create Vector Index Details") + 3. **_OPTIONAL:_** If you want to add meta-data to your documents that you plan on indexing, you must specify those fields in this vector index configuration. If you plan on adding meta-data you will need to reconfigure some of the code in the docs_to_openSearch.py file ![Alt text](images/metadata.png "Add Meta-Data") -## Step 5: -Now that the requirements have been successfully installed in your virtual environment, your OpenSearch Serverless Vector Search and Vector Index are created, we can now begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: -``` -profile_name= + ```zsh + profile_name= opensearch_host= example->abcdefghijklmnop1234.us-east-1.aoss.amazonaws.com vector_index_name= vector_field_name= -``` - -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! - -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 12 in the query_against_openSearch.py file to change the region: - -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock.us-east-1.amazonaws.com') -``` -Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the answer_query() function in the query_against_openSearch.py to look like: - -```python -def answer_query(user_input): - """ - This function takes the user question, creates an embedding of that question, - and performs a KNN search on your Amazon OpenSearch Index. Using the most similar results it feeds that into the Prompt - and LLM as context to generate an answer. - :param user_input: This is the natural language question that is passed in through the app.py file. - :return: The answer to your question from the LLM based on the context that was provided by the KNN search of OpenSearch. - """ - # Setting primary variables, of the user input - userQuery = user_input - # formatting the user input - userQueryBody = json.dumps({"inputText": userQuery}) - # creating an embedding of the user input to perform a KNN search with - userVectors = get_embedding(userQueryBody) - # the query parameters for the KNN search performed by Amazon OpenSearch with the generated User Vector passed in. - # TODO: If you wanted to add pre-filtering on the query you could by editing this query! - query = { - "size": 3, - "query": { - "knn": { - "vectors": { - "vector": userVectors, "k": 3 - } - } - }, - "_source": True, - "fields": ["text"], - } - # performing the search on OpenSearch passing in the query parameters constructed above - response = client.search( - body=query, - index=os.getenv("vector_index_name") - ) - - # Format Json responses into text - similaritysearchResponse = "" - # iterating through all the findings of Amazon openSearch and adding them to a single string to pass in as context - for i in response["hits"]["hits"]: - outputtext = i["fields"]["text"] - similaritysearchResponse = similaritysearchResponse + "Info = " + str(outputtext) - - similaritysearchResponse = similaritysearchResponse - # Configuring the Prompt for the LLM - # TODO: EDIT THIS PROMPT TO OPTIMIZE FOR YOUR USE CASE - prompt_data = f"""\n\nHuman: You are an AI assistant that will help people answer questions they have about [YOUR TOPIC]. Answer the provided question to the best of your ability using the information provided in the Context. - Summarize the answer and provide sources to where the relevant information can be found. - Include this at the end of the response. - Provide information based on the context provided. - Format the output in human readable format - use paragraphs and bullet lists when applicable - Answer in detail with no preamble - If you are unable to answer accurately, please say so. - Please mention the sources of where the answers came from by referring to page numbers, specific books and chapters! - - Question: {userQuery} - - Here is the text you should use as context: {similaritysearchResponse} - - \n\nAssistant: - - """ - # Configuring the model parameters, preparing for inference - # TODO: TUNE THESE PARAMETERS TO OPTIMIZE FOR YOUR USE CASE - body = json.dumps({"prompt": prompt_data, - "max_tokens_to_sample": 4096, - "temperature": 0.5, - "top_k": 250, - "top_p": 0.5, - "stop_sequences": [] - }) - - # Run infernce on the LLM - # Configuring the specific model you are using - modelId = "anthropic.claude-v2" # change this to use a different version from the model provider - accept = "application/json" - contentType = "application/json" - # invoking the bedrock API, passing in all specific parameters - response = bedrock.invoke_model(body=body, - modelId=modelId, - accept=accept, - contentType=contentType) - - # loading in the response from bedrock - response_body = json.loads(response.get('body').read()) - # retrieving the specific completion field, where you answer will be - answer = response_body.get('completion') - # returning the answer as a final result, which ultimately gets returned to the end user - return answer -``` - -You can then change the modelId variable to the model of your choice. - -## Step 6: - -After you create your .env file, it is time to create the embeddings for a sample PDF document of your choosing. + ``` + + +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 12 in the query_against_openSearch.py file to change the region: + + ```zsh + bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock.us-east-1.amazonaws.com') + ``` + + +1. After you create your .env file, it is time to create the embeddings for a sample PDF document of your choosing. All you will need to do, is specify the path to that PDF document in line 42 of the docs_to_openSearch.py file. Optionally you can also try different values for the document chunk size in line 47 - line 51 of the same docs_to_openSearch.py file. -As soon as you are satisfied with the configuration, you can simply run the file while in the root of the repo with the command: - -``` -python3 docs_to_openSearch.py -``` +As soon as you are satisfied with the configuration, you can simply run the file while in the root of the repo with the command below. **_Depending on the size of your document this process can range from seconds to hours_** -## Step 7: -As soon as you have successfully indexed your newly created embeddings within your -Amazon OpenSearch Serverless Vector Search Index, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: + ```zsh + python3 docs_to_openSearch.py + ``` + + +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -``` -streamlit run app.py -``` +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -As soon as the application is up and running in your browser of choice you can begin asking natural language questions against the custom embeddings of the PDF document you created earlier and stored within your Amazon OpenSearch Serverless Vector Store Index. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/requirements.txt index ca4edb3a..a7466dfb 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-rag-opensearch-serverless-poc/requirements.txt @@ -1,81 +1,9 @@ -aiohttp==3.9.2 -aiosignal==1.3.1 -altair==5.1.1 -annotated-types==0.5.0 -anyio==3.7.1 -async-timeout==4.0.3 -attrs==23.1.0 -awscli==1.29.59 -blinker==1.6.2 -boto3==1.28.59 -botocore==1.31.59 -cachetools==5.3.1 -certifi==2023.7.22 -charset-normalizer==3.3.0 -click==8.1.7 -colorama==0.4.4 -dataclasses-json==0.6.1 -docutils==0.16 -exceptiongroup==1.1.3 -frozenlist==1.4.0 -gitdb==4.0.10 -GitPython==3.1.41 -idna==3.4 -importlib-metadata==6.8.0 -Jinja2==3.1.3 -jmespath==1.0.1 -jsonpatch==1.33 -jsonpointer==2.4 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -langchain==0.1.11 -langsmith==0.1.17 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -marshmallow==3.20.1 -mdurl==0.1.2 -multidict==6.0.4 -mypy-extensions==1.0.0 -numpy==1.26.0 -opensearch-py==2.3.1 -packaging==23.2 -pandas==2.1.1 -Pillow==10.2.0 -pip==23.3 -protobuf==4.24.3 -pyarrow==14.0.1 -pyasn1==0.5.0 -pydantic==2.4.2 -pydantic_core==2.10.1 -pydeck==0.8.1b0 -Pygments==2.16.1 -pypdf==3.17.0 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -PyYAML==6.0.1 -referencing==0.30.2 -requests==2.31.0 -rich==13.6.0 -rpds-py==0.10.3 -rsa==4.7.2 -s3transfer==0.7.0 -setuptools==65.5.1 -six==1.16.0 -smmap==5.0.1 -sniffio==1.3.0 -SQLAlchemy==2.0.21 -streamlit==1.30.0 -tenacity==8.2.3 -toml==0.10.2 -toolz==0.12.0 -tornado==6.3.3 -typing_extensions==4.8.0 -typing-inspect==0.9.0 -tzdata==2023.3 -tzlocal==5.0.1 -urllib3==1.26.18 -validators==0.22.0 -wheel==0.38.4 -yarl==1.9.2 -zipp==3.17.0 \ No newline at end of file +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +langchain-community +langchain-experimental +langchain>=0.1.0, <0.2.0 +opensearch-py +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.projen/deps.json new file mode 100644 index 00000000..f45260df --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.projen/deps.json @@ -0,0 +1,30 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "opensearch-py", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/README.md b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/README.md index 86dfcd2e..4b012681 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/README.md @@ -1,126 +1,144 @@ -# RAG with Amazon Bedrock and Semantic Cache +# Amazon Bedrock Semantic Cache POC + +## Overview of Solution This project demonstrates a Retrieval-Augmented Generation (RAG) system using Amazon Bedrock for knowledge retrieval and OpenSearch for semantic caching. It provides a Streamlit-based user interface for asking questions about data stored in Amazon Knowledge Bases. -![Alt text](image/SemanticCache.gif) +![A gif of a screen recording show casing the Amazon Bedrock Semantic Cache POC functionality](images/demo.gif) -## Goal of this Repo -The primary goal of this repository is to showcase an efficient and scalable question-answering system that combines the power of Large Language Models (LLMs) with a knowledge base and semantic caching. This approach aims to: +## Goal of this POC +The primary goal of this repository is to showcase an efficient and scalable question-answering system that combines the power of Large Language Models (LLMs) with a knowledge base and semantic caching. + The approach aims to: + 1. Provide fast and accurate answers to user queries + 2. Reduce the load on the LLM and knowledge base by utilizing a semantic cache + 3. Reduce the cost of the system by limiting calls to the LLM + 4. Demonstrate the integration of Amazon Bedrock and OpenSearch for semantic caching purposes -1. Provide fast and accurate answers to user queries -2. Reduce the load on the LLM and knowledge base by utilizing a semantic cache -3. Reduce the cost of the system by limiting calls to the LLM -4. Demonstrate the integration of Amazon Bedrock and OpenSearch for semantic caching purposes +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](image/semantic-cache-architecture.png "POC architecture") -The application flow is as follows: +When a user interacts with the POC, the flow is as follows: 1. Load documents and crawl websites to add data into knowledge base -2. User submits a question through the Streamlit UI -3. The system checks the semantic cache (OpenSearch) for similar previous queries -4. If a cache hit occurs, the stored answer is returned immediately -5. If no cache hit, the system queries the Amazon Bedrock Knowledge Base for relevant context -6. The retrieved context and user question are sent to an LLM (Claude 3) for answer generation -7. The new question-answer pair is stored in the semantic cache -8. The answer is displayed to the user in the Streamlit interface - -## Project Structure - -- `chat.py`: Main Streamlit application file -- `knowledge_base.py`: Functions for interacting with Amazon Bedrock Knowledge Base -- `semantic_cache.py`: Functions for semantic caching using OpenSearch -- `utils.py`: Utility functions and shared configurations - -## Prerequisites -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. A Amazon Bedrock Knowledge Base with Amazon OpenSearch as the Vector Store. Instructions can be found [here](https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base-create.html). -3. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). - -## Setup and Installation - -1. Clone the repository: -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs/tree/main/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc.git -cd amazon-bedrock-semantic-cache-poc -``` - -2. Create and activate a virtual environment: -``` -python -m venv venv -source venv/bin/activate # On Windows, use venv\Scripts\activate -``` - -3. Install the required dependencies: -``` -pip install -r requirements.txt -``` - -4. Set up your AWS credentials and configure your AWS CLI profile. - -5. Create a `.env` file in the project root with the following variables: -``` -PROFILE_NAME=your_aws_profile_name + +1. User submits a question through the Streamlit UI + +1. The system checks the semantic cache (OpenSearch) for similar previous queries + +1. If a cache hit occurs, the stored answer is returned immediately + +1. If no cache hit, the system queries the Amazon Bedrock Knowledge Base for relevant context + +1. The retrieved context and user question are sent to an LLM (Claude 3) for answer generation + +1. The new question-answer pair is stored in the semantic cache + +1. The answer is displayed to the user in the Streamlit interface + + + + +# How to use this Repo: + +## Prerequisites: + +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. + + +1. A Amazon Bedrock Knowledge Base with Amazon OpenSearch as the Vector Store. Instructions can be found [here](https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base-create.html). + + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `knowledge_base.py` - Functions for interacting with Amazon Bedrock Knowledge Base + + * `semantic_cache.py` - Functions for semantic caching using OpenSearch + + * `utils.py` - Utility functions and shared configurations + + + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main + ``` + +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` + +1. Create a `.env` file in the project root with the following variables: + + ```zsh + PROFILE_NAME=your_aws_profile_name AWS_REGION=your_aws_region OPENSEARCH_HOST=your_opensearch_host OPENSEARCH_INDEX=your_opensearch_index (Note: Specify a name like semantic-cache-index. This will be a seperate index than your knowledge base which will be created by the application) KNOWLEDGE_BASE_ID=your_knowledge_base_id -``` - -Note: you can also export these variables via the CLI - -6. Update OpenSearch permissions to allow access from the CLI and to grant delete actions + ``` -a. Navigate to OpenSearch Serverless Collections -![Alt text](image/os-permissions-1.png) +1. Update OpenSearch permissions to allow access from the CLI and to grant delete actions -b. Select your Collection + a. Navigate to OpenSearch Serverless Collections -![Alt text](image/os-permissions-2.png) + ![Alt text](image/os-permissions-1.png) -c. Click on Data Access Control + b. Select your Collection -![Alt text](image/os-permissions-3.png) + ![Alt text](image/os-permissions-2.png) -d. Select Edit + c. Click on Data Access Control -![Alt text](image/os-permissions-4.png) + ![Alt text](image/os-permissions-3.png) -e. Add your CLI user as a principal + d. Select Edit -![Alt text](image/os-permissions-5.png) + ![Alt text](image/os-permissions-4.png) -f. Grant Delete Collection Items on the collection and Delete Index on the index and click Save + e. Add your CLI user as a principal -![Alt text](image/os-permissions-6.png) + ![Alt text](image/os-permissions-5.png) + f. Grant Delete Collection Items on the collection and Delete Index on the index and click Save -## Running the Application + ![Alt text](image/os-permissions-6.png) -To run the Streamlit application: -1. Ensure you're in the project directory and your virtual environment is activated. +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -2. Run the following command: -``` -streamlit run app.py -``` - -3. Open a web browser and navigate to the URL provided by Streamlit (usually `http://localhost:8501`). +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) ## Considerations -Other vector db's can be used to implement semantic caching. Here a a few helpful links to explore: +Other vector db's can be used to implement semantic caching. Here a a few helpful links to explore: 1. [Semantic Caching with MemoryDB](https://aws.amazon.com/blogs/database/improve-speed-and-reduce-cost-for-generative-ai-workloads-with-a-persistent-semantic-cache-in-amazon-memorydb/) 2. [Semantic Caching with LangChain](https://python.langchain.com/v0.2/docs/integrations/llm_caching/) Please note that only specific models can be used with Amazon Bedrock Knowledge Bases and with the Amazon Bedrock Converse API. 1. Amazon Bedrock Converse API - Supported [models](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html) and model features -2. Amazon Bedrock Knowledge Bases - Supported [models](https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base-supported.html) by action - -## License - -This project is licensed under the MIT License - see the LICENSE file for details. \ No newline at end of file +2. Amazon Bedrock Knowledge Bases - Supported [models](https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base-supported.html) by action \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/app.py b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/app.py new file mode 100644 index 00000000..b2770b19 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/app.py @@ -0,0 +1,5 @@ +import streamlit as st + +st.title('Hello!') +st.write("This is a Streamlit app written in Python.") +st.write("To edit this app, go to `{{ outDir }}`.") \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/semantic-cache-architecture.png b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/architecture.png similarity index 100% rename from genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/semantic-cache-architecture.png rename to genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/architecture.png diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/SemanticCache.gif b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/demo.gif similarity index 100% rename from genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/SemanticCache.gif rename to genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/demo.gif diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/os-permissions-1.png b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/os-permissions-1.png similarity index 100% rename from genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/os-permissions-1.png rename to genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/os-permissions-1.png diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/os-permissions-2.png b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/os-permissions-2.png similarity index 100% rename from genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/os-permissions-2.png rename to genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/os-permissions-2.png diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/os-permissions-3.png b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/os-permissions-3.png similarity index 100% rename from genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/os-permissions-3.png rename to genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/os-permissions-3.png diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/os-permissions-4.png b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/os-permissions-4.png similarity index 100% rename from genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/os-permissions-4.png rename to genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/os-permissions-4.png diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/os-permissions-5.png b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/os-permissions-5.png similarity index 100% rename from genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/os-permissions-5.png rename to genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/os-permissions-5.png diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/os-permissions-6.png b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/os-permissions-6.png similarity index 100% rename from genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/image/os-permissions-6.png rename to genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/images/os-permissions-6.png diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/requirements.txt index 2853f6b1..0d3f7ca3 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-semantic-cache-poc-main/requirements.txt @@ -1,5 +1,6 @@ -boto3>=1.34.84 -botocore>=1.35.5 -python-dotenv==1.0.0 -streamlit==1.30.0 -opensearch-py==2.4.2 \ No newline at end of file +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +opensearch-py +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.projen/deps.json new file mode 100644 index 00000000..6a1b5e45 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.projen/deps.json @@ -0,0 +1,47 @@ +{ + "dependencies": [ + { + "name": "amazon-transcribe", + "type": "runtime" + }, + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "langchain-community", + "type": "runtime" + }, + { + "name": "langchain-experimental", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.1", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "sounddevice", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/README.md index 391941a4..dd465893 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/README.md @@ -1,132 +1,105 @@ -# Amazon-Bedrock-Speech-to-Text-Chat-POC +# Amazon Bedrock Speech to Text POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a ChatGPT alternative using speech-to-text prompts. The application is constructed with a simple streamlit frontend where users can provide zero shot requests using their computer’s microphone and listen to responses to satisfy a broad range of use cases. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Speech to Text POC functionality](images/demo.gif) + +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock in a similar fashion to ChatGPT by invoking the model using their speech rather than typing. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') + + +When a user interacts with the POC, the flow is as follows: + +1. The user makes a "zero-shot" request to the streamlit frontend (app.py) by speaking into their computer’s microphone. + +1. The live audio is streamed to Amazon Transcribe (live_transcription.py) + +1. The transcribed text is streamed back to the streamlit frontend (app.py) once the user has finished speaking. + +1. The application performs a semantic search of the users query against the 1200+ prompts. (prompt_finder_and_invoke_llm.py). + +1. The application returns the 3 most semantically similar prompts, and creates a final prompt that contains the 3 returned prompts along with users query (few-shot prompting) (prompt_finder_and_invoke_llm.py). + +1. The final prompt is passed into Amazon Bedrock to generate an answer to the user’s question (prompt_finder_and_invoke_llm.py). + +1. The final answer is generated by Amazon Bedrock and displayed on the frontend application (app.py). + +1. The final answer is passed to Amazon Polly to convert the text to natural sounding speech (app.py) + +1. The audio file is returned and played through the frontend application (app.py) -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: -1. The user makes a "zero-shot" request to the streamlit frontend (app.py) by speaking into their computer’s microphone. -2. The live audio is streamed to Amazon Transcribe (live_transcription.py) -3. The transcribed text is streamed back to the streamlit frontend (app.py) once the user has finished speaking. -4. The application performs a semantic search of the users query against the 1200+ prompts. (prompt_finder_and_invoke_llm.py). -5. The application returns the 3 most semantically similar prompts, and creates a final prompt that contains the 3 returned prompts along with users query (few-shot prompting) (prompt_finder_and_invoke_llm.py). -6. The final prompt is passed into Amazon Bedrock to generate an answer to the user’s question (prompt_finder_and_invoke_llm.py). -7. The final answer is generated by Amazon Bedrock and displayed on the frontend application (app.py). -8. The final answer is passed to Amazon Polly to convert the text to natural sounding speech (app.py) -9. The audio file is returned and played through the frontend application (app.py). # How to use this Repo: ## Prerequisites: -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). - -## Step 1: - -The first step of utilizing this repo is performing a git clone of the repository. - -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` - -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 5 key files, the app.py file, the prompt_finder_and_invoke_llm.py file, the chat_history_prompt_generator.py file, the live_transcription.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). The prompt_finder_and_invoke_llm.py file houses the logic of the application, including the semantic search against the prompt repository and prompt formatting logic and the Amazon Bedrock API invocations. The chat_history_prompt_generator.py houses the logic required to preserve session state and to dynamically inject the conversation history into prompts to allow for follow-up questions and conversation summary. The live_transcription.py file house the logic required to create an audio stream from the users microphone, send the audio chunks to Amazon Transcribe, and generate a text transcript. The requirements.txt file contains all necessary dependencies for this sample application to work. - -## Step 2: - -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: - -``` -pip install virtualenv -python3.10 -m venv venv -``` - -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: - -``` -cd venv -cd bin -source activate -cd ../../ -``` - -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: - -``` -pip install -r requirements.txt -``` - -## Step 3: - -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: - -``` -profile_name= -``` - -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! - -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 23 in the prompt_finder_and_invoke_llm.py file to set the appropriate region: - -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') -``` - -Since this repository is configured to leverage Claude 3 Haiku, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the llm_answer_generator() function in the prompt_finder_and_invoke_llm.py to look like: - -```python -def llm_answer_generator(question_with_prompt): - """ - This function is used to invoke Amazon Bedrock using the finalized prompt that was created by the prompt_finder(question) - function. - :param question_with_prompt: This is the finalized prompt that includes semantically similar prompts, chat history, - and the users question all in a proper multi-shot format. - :return: The final answer to the users question. - """ - # body of data with parameters that is passed into the bedrock invoke model request - # TODO: TUNE THESE PARAMETERS AS YOU SEE FIT - body = json.dumps({"prompt": question_with_prompt, - "max_tokens_to_sample": 8191, - "temperature": 0, - "top_k": 250, - "top_p": 0.5, - "stop_sequences": [] - }) - # configure model specifics such as specific model - modelId = 'anthropic.claude-v2' - accept = 'application/json' - contentType = 'application/json' - # Invoking the bedrock model with your specifications - response = bedrock.invoke_model(body=body, - modelId=modelId, - accept=accept, - contentType=contentType) - # the body of the response that was generated - response_body = json.loads(response.get('body').read()) - # retrieving the specific completion field, where you answer will be - answer = response_body.get('completion') - # returning the answer as a final result, which ultimately gets returned to the end user - return answer -``` -You can then change the modelId variable to the model of your choice. - -## Step 4: - -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: - -``` -streamlit run app.py -``` - -As soon as the application is up and running in your browser of choice you can begin asking zero-shot questions using your computer’s microphone and leveraging this app as you would ChatGPT. +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. + + + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `chat_history_prompt_generator.py` - logic required to preserve session state and to dynamically inject the conversation history into prompts to allow for follow-up questions and conversation summary. + + * `live_transcription.py` - logic required to create an audio stream from the users microphone, send the audio chunks to Amazon Transcribe, and generate a text transcript. The requirements.txt file contains all necessary dependencies for this sample application to work. + + * `prompt_finder_and_invoke_llm.py` - logic of the application, including the semantic search against the prompt repository and prompt formatting logic and the Amazon Bedrock API invocations. + + + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc + ``` + +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` + +1. create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: + + ```zsh + profile_name= + ``` + + +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 23 in the prompt_finder_and_invoke_llm.py file to set the appropriate region: + + ```zsh + bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') + ``` + + +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. + +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) + diff --git a/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/requirements.txt index 2ea10252..ccea2d06 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-speech-to-text-chat-poc/requirements.txt @@ -1,124 +1,10 @@ -aiohttp==3.9.2 -aiosignal==1.3.1 -altair==5.1.2 -amazon-transcribe==0.6.2 -annotated-types==0.5.0 -anyio==3.7.1 -async-timeout==4.0.3 -attrs==23.1.0 -awscli==1.29.61 -backoff==2.2.1 -bcrypt==4.0.1 -blinker==1.6.2 -boto3==1.28.61 -botocore==1.31.61 -cachetools==5.3.1 -certifi==2023.7.22 -charset-normalizer==3.3.0 -chroma-hnswlib==0.7.3 -chromadb==0.4.13 -click==8.1.7 -colorama==0.4.4 -coloredlogs==15.0.1 -dataclasses-json==0.6.1 -docutils==0.16 -exceptiongroup==1.1.3 -fastapi==0.109.1 -filelock==3.12.4 -flatbuffers==23.5.26 -frozenlist==1.4.0 -fsspec==2023.9.2 -gitdb==4.0.10 -GitPython==3.1.41 -h11==0.14.0 -httptools==0.6.0 -huggingface-hub==0.17.3 -humanfriendly==10.0 -idna==3.4 -importlib-metadata==6.8.0 -importlib-resources==6.1.0 -Jinja2==3.1.3 -jmespath==1.0.1 -joblib==1.3.2 -jsonpatch==1.33 -jsonpointer==2.4 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -langchain==0.1.11 -langchain-community==0.0.31 -langsmith==0.1.17 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -marshmallow==3.20.1 -mdurl==0.1.2 -monotonic==1.6 -mpmath==1.3.0 -multidict==6.0.4 -mypy-extensions==1.0.0 -networkx==3.1 -nltk==3.8.1 -numpy==1.26.0 -onnxruntime==1.16.0 -overrides==7.4.0 -packaging==23.2 -pandas==2.1.1 -Pillow==10.2.0 -pip==23.3 -posthog==3.0.2 -protobuf==4.24.4 -pulsar-client==3.3.0 -pyarrow==14.0.1 -pyasn1==0.5.0 -pydantic==2.4.2 -pydantic_core==2.10.1 -pydeck==0.8.1b0 -Pygments==2.16.1 -PyPika==0.48.9 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -PyYAML==6.0.1 -referencing==0.30.2 -regex==2023.10.3 -requests==2.31.0 -rich==13.6.0 -rpds-py==0.10.4 -rsa==4.7.2 -s3transfer==0.7.0 -safetensors==0.4.0 -scikit-learn==1.3.1 -scipy==1.11.3 -sentencepiece==0.1.99 -sentence-transformers==2.6.1 -setuptools==65.5.1 -six==1.16.0 -smmap==5.0.1 -sniffio==1.3.0 -sounddevice==0.4.6 -SQLAlchemy==2.0.21 -starlette==0.35.0 -streamlit==1.30.0 -sympy==1.12 -tenacity==8.2.3 -threadpoolctl==3.2.0 -tokenizers==0.14.1 -toml==0.10.2 -toolz==0.12.0 -torch==2.1.0 -torchvision==0.16.0 -tornado==6.3.3 -tqdm==4.66.1 -typer==0.9.0 -typing_extensions==4.8.0 -typing-inspect==0.9.0 -tzdata==2023.3 -tzlocal==5.1 -urllib3==1.26.18 -uvicorn==0.23.2 -uvloop==0.17.0 -validators==0.22.0 -watchfiles==0.20.0 -websockets==11.0.3 -wheel==0.38.4 -yarl==1.9.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +amazon-transcribe +boto3 +botocore +langchain-community +langchain-experimental +langchain>=0.1.0, <0.2.0 +python-dotenv +sounddevice +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/README.md index 26055d74..6c9a2275 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/README.md @@ -1,81 +1,92 @@ -# Amazon-Bedrock-Streaming-Response-POC +# Amazon Bedrock Streaming Response POC + +## Overview of Solution + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement streaming responses. The application is constructed with a simple streamlit frontend where users can input zero shot requests directly against the LLM of their choice, leveraging a streaming response technique. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Streaming Response POC functionality](images/demo.gif) + + +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock leveraging its streaming response capabilities. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: +When a user interacts with the POC, the flow is as follows: 1. The user inserts a text question into to the streamlit app. (app.py). -2. The streamlit app, takes the text and passes it into Amazon Bedrock. (invoke_llm_with_streaming.py). -3. A natural language response is streamed to the end user, answering a question in general. (app.py). + +1. The streamlit app, takes the text and passes it into Amazon Bedrock. (invoke_llm_with_streaming.py). + +1. A natural language response is streamed to the end user, answering a question in general. (app.py). + + + # How to use this Repo: ## Prerequisites: -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). - -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. - -``` -https://github.com/aws-samples/genai-quickstart-pocs.git -``` - -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the invoke_llm_with_streaming.py file and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The invoke_llm_with_streaming.py file houses the invocation of Amazon Bedrock with a streaming response, and the basic prompt formatting logic. -The requirements.txt file contains all necessary dependencies for this sample application to work. - -## Step 2: -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: -``` -pip install virtualenv -python3.10 -m venv venv -``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -cd venv -cd bin -source activate -cd ../../ -``` -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: -``` -pip install -r requirements.txt -``` - -## Step 3: -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: - -``` -profile_name= -``` -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! - -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 15 & 39 in the invoke_llm_with_streaming.py file: - -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') - -modelId = 'anthropic.claude-v2' -``` - -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: - -``` -streamlit run app.py -``` -As soon as the application is up and running in your browser of choice you can begin asking zero-shot questions and leveraging Amazon Bedrock's streaming capabilities. +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. + + + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `invoke_llm_with_streaming.py` - The logic required to invoke Amazon Bedrock and stream the response back to the frontend application (app.py). + + + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc + ``` + +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` + +1. create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: + + ```zsh + profile_name= + ``` + + +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 15 & 39 in the invoke_llm_with_streaming.py file: + + ```zsh + bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') + + modelId = 'anthropic.claude-v2' + ``` + + +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. + +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) + diff --git a/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/requirements.txt index 1cfb377a..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-streaming-response-poc/requirements.txt @@ -1,52 +1,5 @@ -altair==5.2.0 -attrs==23.2.0 -blinker==1.7.0 -boto3==1.34.46 -botocore==1.34.46 -cachetools==5.3.2 -certifi==2024.2.2 -charset-normalizer==3.3.2 -click==8.1.7 -gitdb==4.0.11 -GitPython==3.1.42 -idna==3.6 -importlib-metadata==7.0.1 -Jinja2==3.1.3 -jmespath==1.0.1 -jsonschema==4.21.1 -jsonschema-specifications==2023.12.1 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -mdurl==0.1.2 -numpy==1.26.4 -packaging==23.2 -pandas==2.2.0 -pillow==10.2.0 -pip==23.3 -protobuf==4.25.3 -pyarrow==15.0.0 -pydeck==0.8.1b0 -Pygments==2.17.2 -python-dateutil==2.8.2 -python-dotenv==1.0.1 -pytz==2024.1 -referencing==0.33.0 -requests==2.31.0 -rich==13.7.0 -rpds-py==0.18.0 -s3transfer==0.10.0 -setuptools==68.2.0 -six==1.16.0 -smmap==5.0.1 -streamlit==1.31.1 -tenacity==8.2.3 -toml==0.10.2 -toolz==0.12.1 -tornado==6.4 -typing_extensions==4.9.0 -tzdata==2024.1 -tzlocal==5.2 -urllib3==1.26.18 -validators==0.22.0 -wheel==0.41.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.projen/deps.json new file mode 100644 index 00000000..1b5f6b7e --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.projen/deps.json @@ -0,0 +1,43 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "langchain-community", + "type": "runtime" + }, + { + "name": "langchain-experimental", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.1", + "type": "runtime" + }, + { + "name": "pypdf", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/README.md index fa854b96..351c4361 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/README.md @@ -1,130 +1,93 @@ -# Amazon-Bedrock-Summarization-Long-Document-POC +# Amazon Bedrock Summarization of Long Documents POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to implement a long document summarization use case. The application is constructed with a simple streamlit frontend where users can upload large documents and get them summarized. -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Summarization of Long Documents POC functionality](images/demo.gif) + +## Goal of this POC The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to create summaries of large PDF files with chunking logic. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/architecture.png "POC Architecture") -When a user interacts with the GenAI app, the flow is as follows: +When a user interacts with the POC, the flow is as follows: 1. The user uploads a PDF file to the streamlit app. (app.py). -2. The streamlit app, takes the PDF document, saves it, and chunks the document (doc_summarizer.py). -3. Each chunk of the document is passed into Amazon Bedrock, which summarizes each chunk, and then performs a summarization of all chunks (doc_summarizer.py). -4. After the final summarization is completed, the final summary is presented on the streamlit app (app.py). + +1. The streamlit app, takes the PDF document, saves it, and chunks the document (doc_summarizer.py). + +1. Each chunk of the document is passed into Amazon Bedrock, which summarizes each chunk, and then performs a summarization of all chunks (doc_summarizer.py). + +1. After the final summarization is completed, the final summary is presented on the streamlit app (app.py). + + + # How to use this Repo: ## Prerequisites: -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` +## Steps +1. Clone the repository to your local machine. -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the doc_summarizer.py file, and the requirements.txt. The app.py file houses the frontend application (a streamlit app). -The doc_summarizer.py file houses the logic of the application, including the document chunking logic and Amazon Bedrock API invocations. -The requirements.txt file contains all necessary dependencies for this sample application to work. + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `doc_summarizer.py` - The logic required to chunk the document, invoke Amazon Bedrock, and perform the final summarization (doc_summarizer.py). + + -## Step 2: +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc + ``` -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -``` -pip install virtualenv -python3.10 -m venv venv -``` +1. Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: + ```zsh + profile_name= +save_folder= + ``` -``` -cd venv -cd bin -source activate -cd ../../ -``` -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: +1. Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure in the doc_summarizer.py file: -``` -pip install -r requirements.txt -``` + ```zsh + bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock.us-east-1.amazonaws.com' + ``` -## Step 3: -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. + +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -``` -profile_name= -save_folder= -``` - -Please ensure that your AWS CLI Profile has access to Amazon Bedrock, and your Amazon Kendra Index has been created within your AWS account! - -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 15 in the doc_summarizer.py file to set your region: - -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock.us-east-1.amazonaws.com') - -``` -Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the summarizer() function in the doc_summarizer.py file to look like: - -```python -def summarizer(prompt_data) -> str: - """ - This function creates the summary of each individual chunk as well as the final summary. - :param prompt_data: This is the prompt along with the respective chunk of text, at the end it contains all summary chunks combined. - :return: A summary of the respective chunk of data passed in or the final summary that is a summary of all summary chunks. - """ - # setting the key parameters to invoke Amazon Bedrock - body = json.dumps({"prompt": prompt_data, - "max_tokens_to_sample": 8191, - "temperature": 0, - "top_k": 250, - "top_p": 0.5, - "stop_sequences": [] - }) - # the specific Amazon Bedrock model you are using - modelId = 'anthropic.claude-v2' - # type of data that should be expected upon invocation - accept = 'application/json' - contentType = 'application/json' - # the invocation of bedrock, with all of the parameters you have configured - response = bedrock.invoke_model(body=body, - modelId=modelId, - accept=accept, - contentType=contentType) - # gathering the response from bedrock, and parsing to get specifically the answer - response_body = json.loads(response.get('body').read()) - answer = response_body.get('completion') - # returning the final summary for that chunk of text - return answer -``` - -You can then change the modelId variable to the model of your choice. - -## Step 4: - -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: - -``` -streamlit run app.py -``` - -As soon as the application is up and running in your browser of choice you can begin uploading PDF documents and generating summaries. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/requirements.txt index cb662a53..7887ad52 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-summarization-long-document-poc/requirements.txt @@ -1,83 +1,9 @@ -aiohttp==3.9.2 -aiosignal==1.3.1 -altair==5.1.1 -annotated-types==0.5.0 -anyio==3.7.1 -async-timeout==4.0.3 -attrs==23.1.0 -blinker==1.6.2 -boto3==1.28.59 -botocore==1.31.59 -cachetools==5.3.1 -certifi==2023.7.22 -charset-normalizer==3.3.0 -click==8.1.7 -dataclasses-json==0.6.1 -exceptiongroup==1.1.3 -filelock==3.12.4 -frozenlist==1.4.0 -fsspec==2023.9.2 -gitdb==4.0.10 -GitPython==3.1.41 -huggingface-hub==0.17.3 -idna==3.4 -importlib-metadata==6.8.0 -Jinja2==3.1.3 -jmespath==1.0.1 -jsonpatch==1.33 -jsonpointer==2.4 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -langchain==0.1.11 -langsmith==0.1.17 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -marshmallow==3.20.1 -mdurl==0.1.2 -multidict==6.0.4 -mypy-extensions==1.0.0 -numpy==1.26.0 -openai==0.28.1 -packaging==23.2 -pandas==2.1.1 -Pillow==10.2.0 -pip==23.3 -protobuf==4.24.3 -pyarrow==14.0.1 -pydantic==2.4.2 -pydantic_core==2.10.1 -pydeck==0.8.1b0 -Pygments==2.16.1 -pypdf==3.17.0 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3.post1 -PyYAML==6.0.1 -referencing==0.30.2 -regex==2023.8.8 -requests==2.31.0 -rich==13.6.0 -rpds-py==0.10.3 -s3transfer==0.7.0 -safetensors==0.3.3 -setuptools==65.5.1 -six==1.16.0 -smmap==5.0.1 -sniffio==1.3.0 -SQLAlchemy==2.0.21 -streamlit==1.30.0 -tenacity==8.2.3 -tokenizers==0.13.3 -toml==0.10.2 -toolz==0.12.0 -tornado==6.3.3 -tqdm==4.66.1 -typing_extensions==4.8.0 -typing-inspect==0.9.0 -tzdata==2023.3 -tzlocal==5.0.1 -urllib3==1.26.18 -validators==0.22.0 -wheel==0.38.4 -yarl==1.9.2 -zipp==3.17.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +langchain-community +langchain-experimental +langchain>=0.1.0, <0.2.0 +pypdf +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-task-classification/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-task-classification/README.md b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/README.md index a8ea29e4..861683b4 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-task-classification/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/README.md @@ -1,87 +1,91 @@ -# Amazon-Bedrock-CSV-Task-Classification-POC +# Amazon Bedrock Task Classification POC + +## Overview of Solution This sample code demonstrates how to use Amazon Bedrock and Generative AI to implement a task classification bot. The application is constructed with a simple streamlit frontend where users can input a task and get the correct classification which then trigger appropriate downstream workflows to process the task inputted. -![Alt text](public/demo.gif) +![A gif of a screen recording show casing the Amazon Bedrock Task Classification POC functionality](images/demo.gif) -# **Goal of this Repo:** -The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to classify a task, and thus the ability to auto trigger downstream workflows that are designed to process these tasks.
+## Goal of this POC +The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to classify a task, and thus the ability to auto trigger downstream workflows that are designed to process these tasks. This repo comes with a basic front end to help users stand up a proof of concept in just a few minutes. -The architecture of this demo is show below: -![Alt text](public/TaskClassification.jpg "POC architecture") +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') + + +When a user interacts with the POC, the flow is as follows: -When a user interacts with the app, the flow is as follow:
1. The user input task with relevant details into the streamlit app (app.py). -2. The streamlit app, takes the task with description and pass it along to a helper file (task_classification.py). -3. This helper file calls the Bedrock API and wraps the user prompt with a system prompt, parsing user's input and add further requirements. -4. Amazon Bedrock responses to the user's task in 2 items. -* What class the task belongs to -* Model's further processing of task details (to then be pass on to appropriate downstream processes) -5. The application parse the two items from the model outputs to perform next steps (task_classification.py). -6. A visual confirmation on streamlit app (pop up modal) to ensure the correct class is assigned to the task inputted (app.py). -# How to use this Repo: +1. The streamlit app, takes the task with description and pass it along to a helper file (task_classification.py). -## Prerequisites: +1. This helper file calls the Bedrock API and wraps the user prompt with a system prompt, parsing user's input and add further requirements. -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console (Claude Haiku in this demo). -2. Ensure Python3.10 is installed in your machine, it's the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). +1. Amazon Bedrock responses to the user's task in 2 items. + * What class the task belongs to + * Model's further processing of task details (to then be pass on to appropriate downstream processes) -## Step 1: +1. The application parse the two items from the model outputs to perform next steps (task_classification.py). -The first step to utilize this repo is performing a git clone of the repository: +1. A visual confirmation on streamlit app (pop up modal) to ensure the correct class is assigned to the task inputted (app.py). -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` -1. app.py - This file houses the front end application (a streamlit app) -After cloning the repo onto your local machine, open it up in your favourite code editor. The file structure of this repo is broken into 3 key files:
-2. task_classfication.py - This file houses the logic of the application and Amazon Bedrock API invocations. -3. requirements.txt - This file contains all the necessary dependencies for this sample application to work. -## Step 2: -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.10. This can be done by running the following commands: +# How to use this Repo: + +## Prerequisites: + +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -``` -pip install virtualenv -python3.10 -m venv venv -``` -The virtual environment will be extremely useful when you begin the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -source venv/bin/activate -``` +## Steps +1. Clone the repository to your local machine. -After your virtual environment has been created and activated, you can install al the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `task_classification.py` - The logic required to invoke Amazon Bedrock and parse the response + + -``` -pip install -r requirements.txt -``` +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-task-classification + ``` -## Step 3: +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables.
-You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: +1. Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: -``` -profile_name= -``` + ```zsh + profile_name= -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: -``` -streamlit run app.py -``` -As soon as the application is up and running in your browser of choice, you can begin inputting task description. diff --git a/genai-quickstart-pocs-python/amazon-bedrock-task-classification/images/architecture.jpg b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/images/architecture.jpg new file mode 100644 index 0000000000000000000000000000000000000000..04ddb6f3ccffa5fedce334629c9084f5d1f218a4 GIT binary patch literal 58497 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

y5_4Mu?xaBgL@LZLSadPu>?<_s7+)wjn8;* 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 literal 0 HcmV?d00001 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-task-classification/public/demo.gif b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/images/demo.gif similarity index 100% rename from genai-quickstart-pocs-python/amazon-bedrock-task-classification/public/demo.gif rename to genai-quickstart-pocs-python/amazon-bedrock-task-classification/images/demo.gif diff --git a/genai-quickstart-pocs-python/amazon-bedrock-task-classification/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-task-classification/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/requirements.txt index a184063d..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-task-classification/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-task-classification/requirements.txt @@ -1,4 +1,5 @@ -boto3==1.34.94 -botocore==1.34.94 -python-dotenv==1.0.1 -streamlit==1.30.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.projen/deps.json new file mode 100644 index 00000000..811bac7d --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.projen/deps.json @@ -0,0 +1,30 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "pdfplumber", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/README.md index 6be5ceb6..ea19031b 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/README.md @@ -1,72 +1,84 @@ -# Amazon-Bedrock-Text-Extraction-POC +# Amazon Bedrock Text Extraction POC + +## Overview of Solution + This is sample code demonstrating the use of Amazon Bedrock and Generative AI to extract text from a document. The application is constructed with a simple streamlit frontend where users leverage Bedrock Agents to extract and summarize key information from a document like a financial earnings report. -Authored by: Al Destefano and Dom Bavaro - -![Alt text](images/demo.gif) -# **Goal of this Repo:** +![A gif of a screen recording show casing the Amazon Bedrock Text Extraction POC functionality](images/demo.gif) + + +## Goal of this POC The goal of this repo is to provide users with a simple text extraction POC. The example document leveraged is an Amazon Earnings Report and the Agents will extract key information: Report Title, Report Publishing Date, Company Focus, Earnings Per Share (EPS), Net Income, Free Cash Flow, Brief Summary of Report, and a Key Quote from Leadership. This is just one example of text extraction and the prompts can be altered depending on the type of document and information you would like extracted. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') -![Alt text](images/extraction-diagam-image.png "POC Architecture") -The application flow is as follows: +When a user interacts with the POC, the flow is as follows: 1. The user uploads a document to be summarized, in this example we use an earnings report in PDF format into the streamlit app. (app.py). -2. The streamlit app, takes the PDF and passes it into Amazon Bedrock. If you upload another document make sure to update your prompts with what you want extracted/summarized! (extract_pdf_to_json.py). -3. A Bedrock Agent extracts key information and returns it to the user in valid JSON format. (extract_pdf_to_json.py). + +1. The streamlit app, takes the PDF and passes it into Amazon Bedrock. If you upload another document make sure to update your prompts with what you want extracted/summarized! (extract_pdf_to_json.py). + +1. A Bedrock Agent extracts key information and returns it to the user in valid JSON format. (extract_pdf_to_json.py). + + + # How to use this Repo: ## Prerequisites: -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console. -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). - -## Step 1: -The first step of utilizing this repo is performing a git clone of the repository. - -``` -https://github.com/aws-samples/genai-quickstart-pocs.git -``` - -After cloning the repo onto your local machine, open it up in your favorite code editor. The file structure of this repo is broken into 3 key files, -the app.py file, the extract_pdf_to_json.py.py file and the AMZN-Q1-2024-Earnings-Release.pdf. The app.py file houses the frontend application (a streamlit app). -The extract_pdf_to_json.py.py file houses the setup of an Amazon Bedrock Agent and the basic prompt formatting logic. -The AMZN-Q1-2024-Earnings-Release.pdf file contains an example earnings report the user will upload. - -## Step 2: -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: -``` -pip install virtualenv -python3.10 -m venv venv -``` -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: -``` -load_dotenv() -``` - -## Step 3: -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: - -``` -boto3.setup_default_session(profile_name=os.getenv('profile_name')) -``` -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! Next you will setup the Bedrock client: - -``` -config = botocore.config.Config(connect_timeout=300, read_timeout=300) -bedrock = boto3.client('bedrock-runtime' , 'us-east-1', config = config) -``` - -## Step 4: -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements, and created the .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: - -``` -streamlit run app.py -``` -As soon as the application is up and running in your browser of choice you can upload the earnings report (or any other document) and have Amazon Bedrock begin summarizing the document information. +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. + + + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `extract_pdf_to_json.py` - The logic required to invoke Amazon Bedrock and parse the response (extract_pdf_to_json.py). + + * `AMZN-Q1-2024-Earnings-Release.pdf` - contains an example earnings report the user will upload. + + + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc + ``` + +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` + +1. Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: + + ```zsh + profile_name= + ``` + + +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. + +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) + diff --git a/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/requirements.txt index f1f917ce..ab032728 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-text-extraction-poc/requirements.txt @@ -1,5 +1,6 @@ -boto3==1.34.89 -botocore==1.34.89 -pdfplumber==0.11.0 -python-dotenv==1.0.1 -streamlit==1.31.1 \ No newline at end of file +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +pdfplumber +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.projen/deps.json new file mode 100644 index 00000000..691e4b67 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.projen/deps.json @@ -0,0 +1,26 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/README.md index 3359b17a..2b780453 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/README.md @@ -1,140 +1,100 @@ -# Amazon-Bedrock-Translation-POC +# Amazon Bedrock Translation POC + +## Overview of Solution This is sample code demonstrating the use of Amazon Bedrock and Generative AI to translate text from a source to target language. -![Alt text](images/demo.gif) +![A gif of a screen recording show casing the Amazon Bedrock Translation POC functionality](images/demo.gif) -# **Goal of this Repo:** +## Goal of this POC The goal of this repository is to provide users with the ability to use Amazon Bedrock to perform translations. This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. -The architecture and flow of the sample application will be: +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') + + +When a user interacts with the POC, the flow is as follows: -![Alt text](images/architecture.png "POC Architecture") +1. Text: + 1. The user inputs text and selects the source and target language. + 2. The application constructs the appropriate prompt for translation and sends it to Amazon Bedrock. + 3. The appliction recieves and sends the translated text to Amazon Bedrock for analysis of accuracy and fluency. + 4. The translated text and analysis is displayed on the frontend application. -When a user interacts with the translation app they can choose from 3 interfaces (pages), the flow is as follows for each of the pages: +1. Chat: + 1. The user inputs text and selects the target language. + 2. The application constructs the appropriate prompt for translation and sends it to Amazon Bedrock. + 3. The translated response is displayed on the frontend application. + +1. File: + 1. The user uploads a text file and selects the target language. + 2. The application constructs the appropriate prompt for translation and sends it to Amazon Bedrock. + 3. The translated text from the document is displayed on the frontend application. -Text: -1. The user inputs text and selects the source and target language. -2. The application constructs the appropriate prompt for translation and sends it to Amazon Bedrock. -3. The appliction recieves and sends the translated text to Amazon Bedrock for analysis of accuracy and fluency. -4. The translated text and analysis is displayed on the frontend application. -Chat: -1. The user inputs text and selects the target language. -2. The application constructs the appropriate prompt for translation and sends it to Amazon Bedrock. -3. The translated response is displayed on the frontend application. -File: -1. The user uploads a text file and selects the target language. -2. The application constructs the appropriate prompt for translation and sends it to Amazon Bedrock. -3. The translated text from the document is displayed on the frontend application. # How to use this Repo: ## Prerequisites: -1. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console -2. Ensure Python 3.10 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3100/). - -## Step 1: - -The first step of utilizing this repo is performing a git clone of the repository. - -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` - -After cloning the repo onto your local machine, open it up in your favorite code editor.The file structure of this repo is broken into 5 key files, -the Text.py file, the amazon_bedrock_trnaslation.py file, the Chat.py file, the File.py file, and the requirements.txt file. The Text.py, Chat.py, and File.py files house the frontend application (streamlit app) for their corresponding interface. -The amazon_bedrock_translation.py file contains methods which govern the interaction with Amazon Bedrock. -Last, the requirements.txt -file has all the requirements needed to get the sample application up and running. - -## Step 2: - -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.9. This can be done by running the following commands: - -``` -pip install virtualenv -python3.10 -m venv venv -``` - -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: - -``` -cd venv -cd bin -source activate -cd ../../ -``` - -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: - -``` -pip install -r requirements.txt -``` - -## Step 3: - -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. -You will first need to create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: - -``` -profile_name= -``` - -Please ensure that your AWS CLI Profile has access to Amazon Bedrock! - -Depending on the region and model that you are planning to use Amazon Bedrock in, you may need to reconfigure line 23 in the prompt_finder_and_invoke_llm.py file to set the appropriate region: - -``` -bedrock = boto3.client('bedrock-runtime', 'us-east-1', endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com') -``` - -Since this repository is configured to leverage Claude 3, the prompt payload is structured in a different format. If you wanted to leverage other Amazon Bedrock models you can replace the methods in amazon_bedrock_translation.py to utilize: - -```python -def llm_answer_generator(question_with_prompt): - """ - This function is used to invoke Amazon Bedrock using the a generic prompt - """ - prompt = "Prompt text goes here" - # body of data with parameters that is passed into the bedrock invoke model request - # TODO: TUNE THESE PARAMETERS AS YOU SEE FIT - body = json.dumps({"prompt": prompt, - "max_tokens_to_sample": 8191, - "temperature": 0, - "top_k": 250, - "top_p": 0.5, - "stop_sequences": [] - }) - # configure model specifics such as specific model - modelId = 'anthropic.claude-v2' - accept = 'application/json' - contentType = 'application/json' - # Invoking the bedrock model with your specifications - response = bedrock.invoke_model(body=body, - modelId=modelId, - accept=accept, - contentType=contentType) - # the body of the response that was generated - response_body = json.loads(response.get('body').read()) - # retrieving the specific completion field, where you answer will be - answer = response_body.get('completion') - # returning the answer as a final result, which ultimately gets returned to the end user - return answer -``` -You can then change the modelId variable to the model of your choice. - -## Step 4: - -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and created a .env file, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal while in the root of the repositories' directory: - -``` -streamlit run Text.py -``` - -Once the application is up and running in your browser, you can begin translating text, chats, or files. +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. + + + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `Text.py` - Frontend for Text Translate + + * `Chat.py` - Frontend for Chat Translate + + * `File.py` - Frontend for File Translate + + * `amazon_bedrock_translation.py` - Logic required to invoke Amazon Bedrock and parse the response + + * `requirements.txt` - Python dependencies + + + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-translation-poc + ``` + +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` + +1. Create a .env file in the root of this repo. Within the .env file you just created you will need to configure the .env to contain: + + ```zsh + profile_name= + ``` + + +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. + +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) + diff --git a/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/app.py b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/app.py new file mode 100644 index 00000000..b2770b19 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/app.py @@ -0,0 +1,5 @@ +import streamlit as st + +st.title('Hello!') +st.write("This is a Streamlit app written in Python.") +st.write("To edit this app, go to `{{ outDir }}`.") \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/requirements-dev.txt b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/requirements-dev.txt new file mode 100644 index 00000000..5cddc044 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/requirements-dev.txt @@ -0,0 +1,2 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +pytest==7.4.3 diff --git a/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/requirements.txt b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/requirements.txt index f32275e4..c0c70d83 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/requirements.txt +++ b/genai-quickstart-pocs-python/amazon-bedrock-translation-poc/requirements.txt @@ -1,3 +1,5 @@ -boto3==1.26.25 -botocore==1.29.42 -streamlit==1.34.0 +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +boto3 +botocore +python-dotenv +streamlit diff --git a/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.gitattributes b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.gitattributes new file mode 100644 index 00000000..6282fd4f --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.gitattributes @@ -0,0 +1,12 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +* text=auto eol=lf +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/README.md linguist-generated +/requirements-dev.txt linguist-generated +/requirements.txt linguist-generated \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.gitignore b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.gitignore new file mode 100644 index 00000000..70ae3a77 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.gitignore @@ -0,0 +1,85 @@ +# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +/.env +!/requirements.txt +!/requirements-dev.txt +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/README.md diff --git a/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.projen/deps.json b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.projen/deps.json new file mode 100644 index 00000000..a4eb0ded --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.projen/deps.json @@ -0,0 +1,43 @@ +{ + "dependencies": [ + { + "name": "boto3", + "type": "runtime" + }, + { + "name": "botocore", + "type": "runtime" + }, + { + "name": "langchain", + "version": "^0.1", + "type": "runtime" + }, + { + "name": "opensearch-py", + "type": "runtime" + }, + { + "name": "pandas", + "type": "runtime" + }, + { + "name": "python-dotenv", + "type": "runtime" + }, + { + "name": "streamlit", + "type": "runtime" + }, + { + "name": "thefuzz", + "type": "runtime" + }, + { + "name": "pytest", + "version": "7.4.3", + "type": "test" + } + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.projen/files.json b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.projen/files.json new file mode 100644 index 00000000..5c81245c --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.projen/files.json @@ -0,0 +1,13 @@ +{ + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "README.md", + "requirements-dev.txt", + "requirements.txt" + ], + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.projen/tasks.json b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.projen/tasks.json new file mode 100644 index 00000000..da35b784 --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/.projen/tasks.json @@ -0,0 +1,80 @@ +{ + "tasks": { + "build": { + "name": "build", + "description": "Full release build", + "steps": [ + { + "spawn": "pre-compile" + }, + { + "spawn": "compile" + }, + { + "spawn": "post-compile" + }, + { + "spawn": "test" + }, + { + "spawn": "package" + } + ] + }, + "compile": { + "name": "compile", + "description": "Only compile" + }, + "default": { + "name": "default", + "description": "Synthesize project files", + "steps": [ + { + "exec": "npx projen default", + "cwd": "../.." + } + ] + }, + "install": { + "name": "install", + "description": "Install and upgrade dependencies", + "steps": [ + { + "exec": "python -m pip install --upgrade pip" + }, + { + "exec": "pip install -r requirements.txt" + }, + { + "exec": "pip install -r requirements-dev.txt" + } + ] + }, + "package": { + "name": "package", + "description": "Creates the distribution package" + }, + "post-compile": { + "name": "post-compile", + "description": "Runs after successful compilation" + }, + "pre-compile": { + "name": "pre-compile", + "description": "Prepare the project for compilation" + }, + "test": { + "name": "test", + "description": "Run tests", + "steps": [ + { + "exec": "pytest" + } + ] + } + }, + "env": { + "VIRTUAL_ENV": "$(python -c \"import os; print('{0}/.env'.format(os.getcwd()))\")", + "PATH": "$(python -c \"import os, sys; python_dir = 'Scripts' if sys.platform == 'win32' else 'bin'; print('{0}/.env/{1}{2}{3}'.format(os.getcwd(), python_dir, os.pathsep, os.environ['PATH']))\")" + }, + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." +} diff --git a/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/HOWTO.md b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/HOWTO.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/HOWTO.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/README.md b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/README.md index e8af369b..7513291d 100644 --- a/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/README.md +++ b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/README.md @@ -1,102 +1,102 @@ -# Amazon-Bedrock-Video-Chapter-Creator-POC +# Amazon Bedrock Video Chapter Creator POC -This is sample code demonstrating the use of Amazon Transcribe, Amazon OpenSearch Serverless, Amazon Bedrock and Generative AI, to a implement video chapter generator and video search sample. The application is constructed with a simple streamlit frontend where users can upload a video that will be stored, transcribed and have searchable chapters generated. Additionally, if you have videos already uploaded to S3 and have subtitles for the video already created in `.srt` format, you can skip transcribing and jump straight into generating chapters. +## Overview of Solution -The sample also includes a second UI that allows the user to ask about a topic. This will search the video chapters from the videos you've provided and provide a video, set to a specific chapter, that was the closest match to the inquiry. +This is sample code demonstrating the use of Amazon Transcribe, Amazon OpenSearch Serverless, Amazon Bedrock and Generative AI, to a implement video chapter generator and video search sample. + The application is constructed with a simple streamlit frontend where users can upload a video that will be stored, transcribed and have searchable chapters generated. Additionally, if you have videos already uploaded to S3 and have subtitles for the video already created in `.srt` format, you can skip transcribing and jump straight into generating chapters. -![Amazon Bedrock Video Chapter Creator POC Demo](images/demo.gif) -# **Goal of this Repo:** + The sample also includes a second UI that allows the user to ask about a topic. This will search the video chapters from the videos you've provided and provide a video, set to a specific chapter, that was the closest match to the inquiry. -The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to create video chapters and searching those chapters. -This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. - -The architecture and flow of the sample application will be: - -![Alt text](ingest-transcribe-query-workflow.png "POC Architecture") - -When a user interacts with the app, the flow is as follows: +![A gif of a screen recording show casing the Amazon Bedrock Video Chapter Creator POC functionality](images/demo.gif) -1. The user uploads a video file or provides an uploaded file s3 oject to the streamlit app. -2. The streamlit app, takes the video, transcribes it and uses the transcription to determine spots that make sense as chapters. -3. Each chapter is then sent to the LLM to locate a good spot to start the chapter that gives some context as to the content amd doesn't drop the user into the middle of the content. -4. The chapters are then returned to the user, who can then save the chapters to the OpenSearch Collection. -On the search side: -1. The user asks an inquiry via the streamlit app. -2. The query is passed the the LLM with the OpenSearch collection as a source. -3. The OpenSearch collection provides the chapter, which is then returned with the video to set the user to the correct spot in the video. - -# How to use this Repo: - -## Prerequisites: +## Goal of this POC +The goal of this repo is to provide users the ability to use Amazon Bedrock and generative AI to create video chapters and searching those chapters. + This repo comes with a basic frontend to help users stand up a proof of concept in just a few minutes. + The application is constructed with a simple streamlit frontend where users can upload a video that will be stored, transcribed and have searchable chapters generated. Additionally, if you have videos already uploaded to S3 and have subtitles for the video already created in `.srt` format, you can skip transcribing and jump straight into generating chapters. + The sample also includes a second UI that allows the user to ask about a topic. This will search the video chapters from the videos you've provided and provide a video, set to a specific chapter, that was the closest match to the inquiry. -1. Ensure Python 3.11 installed on your machine, it is the most stable version of Python for the packages we will be using, it can be downloaded [here](https://www.python.org/downloads/release/python-3911/). -2. An OpenSearch Serverless Collection. You can learn how to create one [here](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/serverless-vector-search.html). -*The Easy Create instructions on the document are suitable for this* -Within the Collection, a Vector Index is needed, with a Vector Field called `vectors` with an Engine value of `mmslib`, Dimensions of `1536`. The remaining options can be left with their default values. - Note the endpoint for the collection and the name of the index as you will need to use this later. -3. An Amazon S3-Backed CloudFront Distribution. Videos will be uploaded to this S3 bucket and users will access videos through the CloudFront distribution. You can learn how to deploy the CloudFront an S3 bucket configuration [here](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/GettingStarted.SimpleDistribution.html). +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') - Note the hostname of the CloudFront Distribution and the S3 Bucket name and region - you will need this later. -4. Amazon Bedrock Access and CLI Credentials. Ensure that the proper FM model access is provided in the Amazon Bedrock console, as well as access to the resources mentioned in previous prerequisites -## Step 1: +When a user interacts with the POC, the flow is as follows: -The first step of utilizing this repo is performing a git clone of the repository. +1. 1. The user uploads a video file or provides an uploaded file s3 oject to the streamlit app. + 2. The streamlit app, takes the video, transcribes it and uses the transcription to determine spots that make sense as chapters. + 3. Each chapter is then sent to the LLM to locate a good spot to start the chapter that gives some context as to the content amd doesn't drop the user into the middle of the content. + 4. The chapters are then returned to the user, who can then save the chapters to the OpenSearch Collection. -``` -git clone https://github.com/aws-samples/genai-quickstart-pocs.git -``` +1. On the search side: + 1. The user asks an inquiry via the streamlit app. + 2. The query is passed the the LLM with the OpenSearch collection as a source. + 3. The OpenSearch collection provides the chapter, which is then returned with the video to set the user to the correct spot in the video. -After cloning the repo onto your local machine, open it up in your favorite code editor. -## Step 2: -Set up a python virtual environment in the root directory of the repository and ensure that you are using Python 3.11. This can be done by running the following commands (The commands assume you are starting in the root folder of the repository): +# How to use this Repo: -``` -cd amazon-bedrock-video-chapter-creator-poc/ -pip install virtualenv -python3.11 -m venv venv -``` +## Prerequisites: -The virtual environment will be extremely useful when you begin installing the requirements. If you need more clarification on the creation of the virtual environment please refer to this [blog](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/). -After the virtual environment is created, ensure that it is activated, following the activation steps of the virtual environment tool you are using. Likely: +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. -``` -source venv/bin/activate -``` +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. -After your virtual environment has been created and activated, you can install all the requirements found in the requirements.txt file by running this command in the root of this repos directory in your terminal: -``` -pip install -r requirements.txt -``` +1. An OpenSearch Serverless Collection. You can learn how to create one [here](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/serverless-vector-search.html). +*The Easy Create instructions on the document are suitable for this* +Within the Collection, a Vector Index is needed, with a Vector Field called `vectors` with an Engine value of `mmslib`, Dimensions of `1536`. The remaining options can be left with their default values. -## Step 3: - -Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. +1. An Amazon S3-Backed CloudFront Distribution. Videos will be uploaded to this S3 bucket and users will access videos through the CloudFront distribution. You can learn how to deploy the CloudFront an S3 bucket configuration [here](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/GettingStarted.SimpleDistribution.html). + + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + + The file structure of this POC is broken into these files + + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + + + * `videochapterlogic.py` - This is the logic that the UI connects to. The functions perform the logic and API calls to the AWS service endpoints like Amazon Transcribe, Amazon Bedrock, etc. `app.py` imports `videochapterlogic` functions. + + * `environment.toml` - This is the file that contains the configurations specific to your AWS environment like the S3 Bucket or OpenSearch Collection endpoint. The values in this file are required in order for the application to function. + + * `.streamlit/config.toml` - The streamlit configuration file with paremters set to override the default configuration. Generally you won't need to adjust this unless you want to further customize the streamlit app. + + + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc + ``` + +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` + +1. Now that the requirements have been successfully installed in your virtual environment we can begin configuring environment variables. Open the `environment.toml` file and fill in the properties with your resources -## Step 4: - -As soon as you have successfully cloned the repo, created a virtual environment, activated it, installed the requirements.txt, and setup your environment.toml, your application should be ready to go. -To start up the application with its basic frontend you simply need to run the following command in your terminal: -**Running the UI** -``` -streamlit run app.py -``` +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. -# POC Environment -This section will walk you through the various files that exist in this POC directory. +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) -* `app.py` - This the main application that generates the UI through streamlit. (See above). -* `videochapterlogic.py` - This is the logic that the UI connects to. The functions perform the logic and API calls to the AWS service endpoints like Amazon Transcribe, Amazon Bedrock, etc. `app.py` imports `videochapterlogic` functions. -* `environment.toml` - This is the file that contains the configurations specific to your AWS environment like the S3 Bucket or OpenSearch Collection endpoint. The values in this file are required in order for the application to function. -* `.streamlit/config.toml` - The streamlit configuration file with paremters set to override the default configuration. Generally you won't need to adjust this unless you want to further customize the streamlit app. -* `requirements.txt` - The python packages required for the app to function. You will reference this during setup (see above). \ No newline at end of file diff --git a/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/images/architecture.png b/genai-quickstart-pocs-python/amazon-bedrock-video-chapter-creator-poc/images/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..0c29074d6e3c8d6d82a489695cf0481356007afe GIT binary patch literal 119756 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.1.0, <0.2.0 +opensearch-py +pandas +python-dotenv +streamlit +thefuzz diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..49230de4 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6789 @@ +{ + "name": "genai-quickstart-pocs", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "genai-quickstart-pocs", + "version": "0.0.0", + "license": "Apache-2.0", + "dependencies": { + "nunjucks": "^3.2.4" + }, + "devDependencies": { + "@types/node": "^22.7.4", + "@types/nunjucks": "^3.2.6", + "@typescript-eslint/eslint-plugin": "^7", + "@typescript-eslint/parser": "^7", + "commit-and-tag-version": "^12", + "constructs": "^10.0.0", + "eslint": "^8", + "eslint-import-resolver-typescript": "^3.6.3", + "eslint-plugin-import": "^2.30.0", + "projen": "^0.88.0", + "ts-node": "^10.9.2", + "typescript": "^5.6.2" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.25.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hutson/parse-repository-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", + "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/nunjucks": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@types/nunjucks/-/nunjucks-3.2.6.tgz", + "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/add-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", + "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/commit-and-tag-version": { + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/commit-and-tag-version/-/commit-and-tag-version-12.5.0.tgz", + "integrity": "sha512-Ll7rkKntH20iEFOPUT4e503Jf3J0J8jSN+aSeHuvNdtv4xmv9kSLSBg2CWsMVihwF3J2WvMHBEUSCKuDNesiTA==", + "dev": true, + "license": "ISC", + "dependencies": { + "chalk": "^2.4.2", + "conventional-changelog": "4.0.0", + "conventional-changelog-config-spec": "2.1.0", + "conventional-changelog-conventionalcommits": "6.1.0", + "conventional-recommended-bump": "7.0.1", + "detect-indent": "^6.0.0", + "detect-newline": "^3.1.0", + "dotgitignore": "^2.1.0", + "figures": "^3.1.0", + "find-up": "^5.0.0", + "git-semver-tags": "^5.0.0", + "jsdom": "^25.0.0", + "semver": "^7.6.3", + "w3c-xmlserializer": "^5.0.0", + "yaml": "^2.4.1", + "yargs": "^17.7.2" + }, + "bin": { + "commit-and-tag-version": "bin/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/constructs": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.4.2.tgz", + "integrity": "sha512-wsNxBlAott2qg8Zv87q3eYZYgheb9lchtBfjHzzLHtXbttwSrHPs1NNQbBrmbb1YZvYg2+Vh0Dor76w4mFxJkA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/conventional-changelog": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-4.0.0.tgz", + "integrity": "sha512-JbZjwE1PzxQCvm+HUTIr+pbSekS8qdOZzMakdFyPtdkEWwFvwEJYONzjgMm0txCb2yBcIcfKDmg8xtCKTdecNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-changelog-angular": "^6.0.0", + "conventional-changelog-atom": "^3.0.0", + "conventional-changelog-codemirror": "^3.0.0", + "conventional-changelog-conventionalcommits": "^6.0.0", + "conventional-changelog-core": "^5.0.0", + "conventional-changelog-ember": "^3.0.0", + "conventional-changelog-eslint": "^4.0.0", + "conventional-changelog-express": "^3.0.0", + "conventional-changelog-jquery": "^4.0.0", + "conventional-changelog-jshint": "^3.0.0", + "conventional-changelog-preset-loader": "^3.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", + "integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-atom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-3.0.0.tgz", + "integrity": "sha512-pnN5bWpH+iTUWU3FaYdw5lJmfWeqSyrUkG+wyHBI9tC1dLNnHkbAOg1SzTQ7zBqiFrfo55h40VsGXWMdopwc5g==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-codemirror": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-3.0.0.tgz", + "integrity": "sha512-wzchZt9HEaAZrenZAUUHMCFcuYzGoZ1wG/kTRMICxsnW5AXohYMRxnyecP9ob42Gvn5TilhC0q66AtTPRSNMfw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-config-spec": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", + "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-6.1.0.tgz", + "integrity": "sha512-3cS3GEtR78zTfMzk0AizXKKIdN4OvSh7ibNz6/DPbhWWQu7LqE/8+/GqSodV+sywUR2gpJAdP/1JFf4XtN7Zpw==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-core": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-5.0.2.tgz", + "integrity": "sha512-RhQOcDweXNWvlRwUDCpaqXzbZemKPKncCWZG50Alth72WITVd6nhVk9MJ6w1k9PFNBcZ3YwkdkChE+8+ZwtUug==", + "dev": true, + "license": "MIT", + "dependencies": { + "add-stream": "^1.0.0", + "conventional-changelog-writer": "^6.0.0", + "conventional-commits-parser": "^4.0.0", + "dateformat": "^3.0.3", + "get-pkg-repo": "^4.2.1", + "git-raw-commits": "^3.0.0", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^5.0.0", + "normalize-package-data": "^3.0.3", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-ember": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-3.0.0.tgz", + "integrity": "sha512-7PYthCoSxIS98vWhVcSphMYM322OxptpKAuHYdVspryI0ooLDehRXWeRWgN+zWSBXKl/pwdgAg8IpLNSM1/61A==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-eslint": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-4.0.0.tgz", + "integrity": "sha512-nEZ9byP89hIU0dMx37JXQkE1IpMmqKtsaR24X7aM3L6Yy/uAtbb+ogqthuNYJkeO1HyvK7JsX84z8649hvp43Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-express": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-3.0.0.tgz", + "integrity": "sha512-HqxihpUMfIuxvlPvC6HltA4ZktQEUan/v3XQ77+/zbu8No/fqK3rxSZaYeHYant7zRxQNIIli7S+qLS9tX9zQA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-jquery": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-4.0.0.tgz", + "integrity": "sha512-TTIN5CyzRMf8PUwyy4IOLmLV2DFmPtasKN+x7EQKzwSX8086XYwo+NeaeA3VUT8bvKaIy5z/JoWUvi7huUOgaw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-jshint": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-3.0.0.tgz", + "integrity": "sha512-bQof4byF4q+n+dwFRkJ/jGf9dCNUv4/kCDcjeCizBvfF81TeimPZBB6fT4HYbXgxxfxWXNl/i+J6T0nI4by6DA==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-preset-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-3.0.0.tgz", + "integrity": "sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-writer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-6.0.1.tgz", + "integrity": "sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-commits-filter": "^3.0.0", + "dateformat": "^3.0.3", + "handlebars": "^4.7.7", + "json-stringify-safe": "^5.0.1", + "meow": "^8.1.2", + "semver": "^7.0.0", + "split": "^1.0.1" + }, + "bin": { + "conventional-changelog-writer": "cli.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-commits-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-3.0.0.tgz", + "integrity": "sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-commits-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz", + "integrity": "sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.3.5", + "meow": "^8.1.2", + "split2": "^3.2.2" + }, + "bin": { + "conventional-commits-parser": "cli.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-recommended-bump": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-7.0.1.tgz", + "integrity": "sha512-Ft79FF4SlOFvX4PkwFDRnaNiIVX7YbmqGU0RwccUaiGvgp3S0a8ipR2/Qxk31vclDNM+GSdJOVs2KrsUCjblVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "concat-stream": "^2.0.0", + "conventional-changelog-preset-loader": "^3.0.0", + "conventional-commits-filter": "^3.0.0", + "conventional-commits-parser": "^4.0.0", + "git-raw-commits": "^3.0.0", + "git-semver-tags": "^5.0.0", + "meow": "^8.1.2" + }, + "bin": { + "conventional-recommended-bump": "cli.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssstyle": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "rrweb-cssom": "^0.7.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotgitignore": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", + "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", + "dev": true, + "license": "ISC", + "dependencies": { + "find-up": "^3.0.0", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/dotgitignore/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dotgitignore/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dotgitignore/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz", + "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.5", + "enhanced-resolve": "^5.15.0", + "eslint-module-utils": "^2.8.1", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-pkg-repo": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", + "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@hutson/parse-repository-url": "^3.0.0", + "hosted-git-info": "^4.0.0", + "through2": "^2.0.0", + "yargs": "^16.2.0" + }, + "bin": { + "get-pkg-repo": "src/cli.js" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-pkg-repo/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/get-pkg-repo/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/git-raw-commits": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-3.0.0.tgz", + "integrity": "sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dargs": "^7.0.0", + "meow": "^8.1.2", + "split2": "^3.2.2" + }, + "bin": { + "git-raw-commits": "cli.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/git-remote-origin-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", + "integrity": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/git-semver-tags": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-5.0.1.tgz", + "integrity": "sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==", + "dev": true, + "license": "MIT", + "dependencies": { + "meow": "^8.1.2", + "semver": "^7.0.0" + }, + "bin": { + "git-semver-tags": "cli.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/gitconfiglocal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", + "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==", + "dev": true, + "license": "BSD", + "dependencies": { + "ini": "^1.3.2" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz", + "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.6.3" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.1.0", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC" + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.ismatch": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/meow/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/meow/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/meow/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/meow/node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/meow/node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/meow/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "license": "BSD-2-Clause", + "dependencies": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "bin": { + "nunjucks-precompile": "bin/precompile" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/nwsapi": { + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.0.tgz", + "integrity": "sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/projen": { + "version": "0.88.3", + "resolved": "https://registry.npmjs.org/projen/-/projen-0.88.3.tgz", + "integrity": "sha512-VTH2orA3HIrgzdL89w8O2oaogUbKHaORYtM6H/v2biHwNqNJR998MV2eGq4tvynJE/VjFKNZWbf0mveg7p+36w==", + "bundleDependencies": [ + "@iarna/toml", + "case", + "chalk", + "comment-json", + "conventional-changelog-config-spec", + "fast-json-patch", + "glob", + "ini", + "semver", + "shx", + "xmlbuilder2", + "yaml", + "yargs" + ], + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@iarna/toml": "^2.2.5", + "case": "^1.6.3", + "chalk": "^4.1.2", + "comment-json": "4.2.2", + "constructs": "^10.0.0", + "conventional-changelog-config-spec": "^2.1.0", + "fast-json-patch": "^3.1.1", + "glob": "^8", + "ini": "^2.0.0", + "semver": "^7.6.3", + "shx": "^0.3.4", + "xmlbuilder2": "^3.1.1", + "yaml": "^2.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "projen": "bin/projen" + }, + "engines": { + "node": ">= 16.0.0" + }, + "peerDependencies": { + "constructs": "^10.0.0" + } + }, + "node_modules/projen/node_modules/@iarna/toml": { + "version": "2.2.5", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/projen/node_modules/@oozcitak/dom": { + "version": "1.15.10", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "@oozcitak/infra": "1.0.8", + "@oozcitak/url": "1.0.4", + "@oozcitak/util": "8.3.8" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/projen/node_modules/@oozcitak/infra": { + "version": "1.0.8", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "@oozcitak/util": "8.3.8" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/projen/node_modules/@oozcitak/url": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "@oozcitak/infra": "1.0.8", + "@oozcitak/util": "8.3.8" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/projen/node_modules/@oozcitak/util": { + "version": "8.3.8", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/projen/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/projen/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/projen/node_modules/argparse": { + "version": "1.0.10", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/projen/node_modules/array-timsort": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/projen/node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/projen/node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/projen/node_modules/case": { + "version": "1.6.3", + "dev": true, + "inBundle": true, + "license": "(MIT OR GPL-3.0-or-later)", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/projen/node_modules/chalk": { + "version": "4.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/projen/node_modules/cliui": { + "version": "8.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/projen/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/projen/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/projen/node_modules/comment-json": { + "version": "4.2.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "array-timsort": "^1.0.3", + "core-util-is": "^1.0.3", + "esprima": "^4.0.1", + "has-own-prop": "^2.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/projen/node_modules/concat-map": { + "version": "0.0.1", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/projen/node_modules/conventional-changelog-config-spec": { + "version": "2.1.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/projen/node_modules/core-util-is": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/projen/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/projen/node_modules/escalade": { + "version": "3.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/projen/node_modules/esprima": { + "version": "4.0.1", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/projen/node_modules/fast-json-patch": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/projen/node_modules/fs.realpath": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/projen/node_modules/function-bind": { + "version": "1.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/projen/node_modules/get-caller-file": { + "version": "2.0.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/projen/node_modules/glob": { + "version": "8.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/projen/node_modules/glob/node_modules/minimatch": { + "version": "5.1.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/projen/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/projen/node_modules/has-own-prop": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/projen/node_modules/hasown": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/projen/node_modules/inflight": { + "version": "1.0.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/projen/node_modules/inherits": { + "version": "2.0.4", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/projen/node_modules/ini": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/projen/node_modules/interpret": { + "version": "1.4.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/projen/node_modules/is-core-module": { + "version": "2.15.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/projen/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/projen/node_modules/js-yaml": { + "version": "3.14.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/projen/node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/projen/node_modules/minimatch/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/projen/node_modules/minimist": { + "version": "1.2.8", + "dev": true, + "inBundle": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/projen/node_modules/once": { + "version": "1.4.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/projen/node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/projen/node_modules/path-parse": { + "version": "1.0.7", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/projen/node_modules/rechoir": { + "version": "0.6.2", + "dev": true, + "inBundle": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/projen/node_modules/repeat-string": { + "version": "1.6.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/projen/node_modules/require-directory": { + "version": "2.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/projen/node_modules/resolve": { + "version": "1.22.8", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/projen/node_modules/semver": { + "version": "7.6.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/projen/node_modules/shelljs": { + "version": "0.8.5", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/projen/node_modules/shelljs/node_modules/glob": { + "version": "7.2.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/projen/node_modules/shx": { + "version": "0.3.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.3", + "shelljs": "^0.8.5" + }, + "bin": { + "shx": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/projen/node_modules/sprintf-js": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause" + }, + "node_modules/projen/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/projen/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/projen/node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/projen/node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/projen/node_modules/wrap-ansi": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/projen/node_modules/wrappy": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/projen/node_modules/xmlbuilder2": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "@oozcitak/dom": "1.15.10", + "@oozcitak/infra": "1.0.8", + "@oozcitak/util": "8.3.8", + "js-yaml": "3.14.1" + }, + "engines": { + "node": ">=12.0" + } + }, + "node_modules/projen/node_modules/y18n": { + "version": "5.0.8", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/projen/node_modules/yaml": { + "version": "2.6.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/projen/node_modules/yargs": { + "version": "17.7.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/projen/node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "license": "ISC", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/tldts": { + "version": "6.1.51", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.51.tgz", + "integrity": "sha512-33lfQoL0JsDogIbZ8fgRyvv77GnRtwkNE/MOKocwUgPO1WrSfsq7+vQRKxRQZai5zd+zg97Iv9fpFQSzHyWdLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.51" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.51", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.51.tgz", + "integrity": "sha512-bu9oCYYWC1iRjx+3UnAjqCsfrWNZV1ghNQf49b3w5xE8J/tNShHTzp5syWJfwGH+pxUgTTLUnzHnfuydW7wmbg==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..34d0cf00 --- /dev/null +++ b/package.json @@ -0,0 +1,51 @@ +{ + "name": "genai-quickstart-pocs", + "scripts": { + "build": "npx projen build", + "bump": "npx projen bump", + "clobber": "npx projen clobber", + "compile": "npx projen compile", + "default": "npx projen default", + "eject": "npx projen eject", + "eslint": "npx projen eslint", + "package": "npx projen package", + "post-compile": "npx projen post-compile", + "post-upgrade": "npx projen post-upgrade", + "pre-compile": "npx projen pre-compile", + "release": "npx projen release", + "test": "npx projen test", + "unbump": "npx projen unbump", + "upgrade": "npx projen upgrade", + "watch": "npx projen watch", + "projen": "npx projen" + }, + "author": { + "name": "AWS", + "organization": false + }, + "devDependencies": { + "@types/node": "^22.7.4", + "@types/nunjucks": "^3.2.6", + "@typescript-eslint/eslint-plugin": "^7", + "@typescript-eslint/parser": "^7", + "commit-and-tag-version": "^12", + "constructs": "^10.0.0", + "eslint": "^8", + "eslint-import-resolver-typescript": "^3.6.3", + "eslint-plugin-import": "^2.30.0", + "projen": "^0.88.0", + "ts-node": "^10.9.2", + "typescript": "^5.6.2" + }, + "dependencies": { + "nunjucks": "^3.2.4" + }, + "main": "lib/index.js", + "license": "Apache-2.0", + "publishConfig": { + "access": "public" + }, + "version": "0.0.0", + "types": "lib/index.d.ts", + "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." +} diff --git a/projenrc/projects/core-readme-component.ts b/projenrc/projects/core-readme-component.ts new file mode 100644 index 00000000..0e010861 --- /dev/null +++ b/projenrc/projects/core-readme-component.ts @@ -0,0 +1,30 @@ +import fs from 'fs'; +import path from 'path'; +import * as nunjucks from 'nunjucks'; +import { Component, Project, TextFile } from 'projen'; +import { POCReadmeDetails } from './resources/types'; + +export class READMEComponent extends Component { + private pythonPocs: POCReadmeDetails[]; + private dotNetPocs: POCReadmeDetails[]; + constructor(scope: Project, id: string, pythonPocs: POCReadmeDetails[], dotNetPocs: POCReadmeDetails[]) { + super(scope, id); + this.dotNetPocs = dotNetPocs; + this.pythonPocs = pythonPocs; + } + + synthesize(): void { + this.project.tryRemoveFile('README.md'); + const README_TEMPLATE = path.join(__dirname, 'resources', 'root-readme.md'); + const readmeTemplate = fs.readFileSync(README_TEMPLATE, 'utf-8'); + const renderedReadmeContent = nunjucks.renderString(readmeTemplate, { + pocs: { + pythonPocs: this.pythonPocs, + dotNetPocs: this.dotNetPocs, + }, + }); + new TextFile(this.project, 'README.md', { + lines: renderedReadmeContent.split('\n'), + }); + } +} \ No newline at end of file diff --git a/projenrc/projects/dot-net-quickstart-pocs.ts b/projenrc/projects/dot-net-quickstart-pocs.ts new file mode 100644 index 00000000..e45f2b54 --- /dev/null +++ b/projenrc/projects/dot-net-quickstart-pocs.ts @@ -0,0 +1,12 @@ +import { POCReadmeDetails } from './resources/types'; +export class DotNetQuickStartPOCs { + private _dotNetPocs: POCReadmeDetails[] = []; + + public addPoc (pocDetails: POCReadmeDetails): void { + this._dotNetPocs.push(pocDetails); + }; + + public get dotNetPocs(): POCReadmeDetails[] { + return this._dotNetPocs; + } +} \ No newline at end of file diff --git a/projenrc/projects/resources/root-readme.md b/projenrc/projects/resources/root-readme.md new file mode 100644 index 00000000..4bdb7041 --- /dev/null +++ b/projenrc/projects/resources/root-readme.md @@ -0,0 +1,64 @@ +# GenAI Quick Start PoCs + +This repository contains sample code demonstrating various use cases leveraging Amazon Bedrock and Generative AI. Each sample is a separate project with its own directory, and includes a basic Streamlit frontend to help users quickly set up a proof of concept. + +##### Authors: Brian Maguire, Dom Bavaro, Ryan Doty, Sudeesh Sasidharan, Tarik Makota, Addie Rudy + +## Sample Proof of Concepts - Python + +{% if pocs.pythonPocs %} +{% for pythonPoc in pocs.pythonPocs %} +1. **{{ pythonPoc.pocName }}** + {{pythonPoc.pocDescription}} + {% if pythonPoc.architectureImage %} + ![Screen Recording of {{pythonPoc.pocName}}]({{pythonPoc.imagePath}}) + {% endif %} +{% endfor %} +{% endif %} + +## Sample Proof of Concepts - .NET + +{% if pocs.dotNetPocs %} +{% for dotNetPocs in pocs.dotNetPocs %} +1. **{{ dotNetPocs.pocName }}** + {{dotNetPocs.pocDescription}} + {% if dotNetPocs.architectureImage %} + ![Screen Recording of {{dotNetPocs.pocName}}]({{dotNetPocs.imagePath}}) + {% endif %} +{% endfor %} +{% endif %} + + +## Prerequisites - Python + +- Amazon Bedrock Access and CLI Credentials +- Python 3.10 installed on your machine +- Additional prerequisites specific to each sample (e.g., RDS Database, Amazon Kendra index, etc.) + +## Prerequisites - .NET + +- Amazon Bedrock Access and CLI Credentials (Please ensure your AWS CLI Profile has access to Amazon Bedrock!) +- .NET 8.0 +- Visual Studio installed on your machine +- Additional prerequisites specific to each sample (e.g., RDS Database, Amazon Kendra index, etc.) +- Configure the necessary environment variables (e.g., AWS credentials, database connections, etc.). +- Access to Claude 3 haiku model. Please follow this [AWS Documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html) to get access to the model. +- Run Blazor app + +## Getting Started + +1. Clone the repository. +2. Navigate to the desired sample directory. +3. Set up a Python virtual environment and install the required dependencies. +4. Configure the necessary environment variables (e.g., AWS credentials, database connections, etc.). +5. Run the Streamlit application using the provided command. + +Detailed instructions for each sample are provided in their respective directories. + +## Security + +See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. + +## License + +This library is licensed under the MIT-0 License. See the LICENSE file. diff --git a/projenrc/projects/resources/streamlit-app.py b/projenrc/projects/resources/streamlit-app.py new file mode 100644 index 00000000..b2770b19 --- /dev/null +++ b/projenrc/projects/resources/streamlit-app.py @@ -0,0 +1,5 @@ +import streamlit as st + +st.title('Hello!') +st.write("This is a Streamlit app written in Python.") +st.write("To edit this app, go to `{{ outDir }}`.") \ No newline at end of file diff --git a/projenrc/projects/resources/streamlit-howto.md b/projenrc/projects/resources/streamlit-howto.md new file mode 100644 index 00000000..5e6c51bf --- /dev/null +++ b/projenrc/projects/resources/streamlit-howto.md @@ -0,0 +1,7 @@ +# POC Usage Guide + +This guide covers how to use the Streamlit POC in the browser. +For information guidance on downloading and running the POC, please visit the [README](README.md) +--- + +** Replace this section with a walk through ** \ No newline at end of file diff --git a/projenrc/projects/resources/streamlit-readme.md b/projenrc/projects/resources/streamlit-readme.md new file mode 100644 index 00000000..46ff0fef --- /dev/null +++ b/projenrc/projects/resources/streamlit-readme.md @@ -0,0 +1,81 @@ +# {{ pocTitle }} + +## Overview of Solution + +{{ pocOverview }} + +![A gif of a screen recording show casing the {{ pocTitle }} functionality](images/demo.gif) + +{% if pocGoal %} +## Goal of this POC +{{pocGoal.overview}} +{% if pocGoal.architectureImage %} +The architecture & flow of the POC is as follows: +![POC Architecture & Flow](images/architecture.png 'POC Architecture') +{% endif %} +{% if pocGoal.flowSteps %} +When a user interacts with the POC, the flow is as follows: +{% for step in pocGoal.flowSteps %} +1. {{step}} +{% endfor %} +{% endif %} +{% endif %} + +# How to use this Repo: + +## Prerequisites: + +1. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured with access to Amazon Bedrock. + +1. [Python](https://www.python.org/downloads/) v3.11 or greater. The POC runs on python. + +{% for prereq in additionalPrerequisits %} +1. {{prereq | safe}} +{% endfor %} + +## Steps +1. Clone the repository to your local machine. + + ``` + git clone https://github.com/aws-samples/genai-quickstart-pocs.git + ``` + {% if fileWalkthrough %} + The file structure of this POC is broken into these files + {% if fileWalkthrough != false %} + * `requirements.txt` - all the requirements needed to get the sample application up and running. + * `app.py` - The streamlit frontend + {% endif %} + {% for pocFile in fileWalkthrough.files %} + * `{{pocFile.name}}` - {{pocFile.description}} + {% endfor %} + {% endif %} + +1. Open the repository in your favorite code editor. In the terminal, navigate to the POC's folder: + ```zsh + cd {{pocPath}} + ``` + +1. Configure the python virtual environment, activate it & install project dependencies. *Note: each POC has it's own dependencies & dependency management.* + ```zsh + python -m venv .env + source .env/bin/activate + pip install -r requirements.txt + ``` +{% for step in extraSteps %} +1. {{ step.instructions }} +{% if step.command %} + ```zsh + {{ step.command | safe }} + ``` +{% endif %} +{% endfor %} +1. Start the POC from your terminal + ```zsh + streamlit run app.py + ``` +This should start the POC and open a browser window to the application. + +## How-To Guide +For a details how-to guide for using this poc, visit [HOWTO.md](HOWTO.md) + +{{ finalText }} \ No newline at end of file diff --git a/projenrc/projects/resources/types.ts b/projenrc/projects/resources/types.ts new file mode 100644 index 00000000..634814e6 --- /dev/null +++ b/projenrc/projects/resources/types.ts @@ -0,0 +1,6 @@ +export interface POCReadmeDetails { + pocName: string; + pocDescription: string; + imagePath?: string; + architectureImage?: boolean; +} \ No newline at end of file diff --git a/projenrc/projects/streamlit-quickstart-poc.ts b/projenrc/projects/streamlit-quickstart-poc.ts new file mode 100644 index 00000000..216227e8 --- /dev/null +++ b/projenrc/projects/streamlit-quickstart-poc.ts @@ -0,0 +1,156 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as nunjucks from 'nunjucks'; +import { Component, Project, SampleFile, TextFile } from 'projen'; +import { PythonProject } from 'projen/lib/python'; +import { POCReadmeDetails } from './resources/types'; + +interface StreamlitQuickStartPOCProps { + parentProject: Project; + pocName: string; + pocPackageName: string; + pocDescription?: string; + additionalDeps?: string[]; + excludeFromReadmeManagement?: boolean; + readme?: { + additionalPrerequisits?: string[]; + pocGoal?: { + overview: string; + architectureImage: boolean; + flowSteps?: string[]; + }; + /** + * File walkthrough for the project + * Note: by default app.py, requirements.txt are already included. + */ + fileWalkthrough?: { + includeDefaults?: boolean; + files: Array<{ + name: string; + description: string; + }>; + }; + extraSteps?: Array<{ + instructions: string; + command?: string; + }>; + /** + * Any additional text to include at the end. + */ + finalText?: string; + }; + skipApp?: boolean; +} + + +export class StreamlitQuickStartPOC extends PythonProject { + private pocProps: StreamlitQuickStartPOCProps; + constructor(props: StreamlitQuickStartPOCProps) { + super({ + parent: props.parentProject, + outdir: path.join('genai-quickstart-pocs-python', props.pocPackageName), + projenrcTs: true, + name: props.pocPackageName, + description: props.pocDescription, + deps: [ + 'streamlit', + 'boto3', + 'botocore', + 'python-dotenv', + ], + pip: true, + venv: true, + sample: false, + authorEmail: 'no-email@aws.amazon.com', + authorName: 'AWS', + license: 'MIT-0', + moduleName: props.pocPackageName, + version: '0.0.1', + github: false, + }); + this.pocProps = props; + for (const dep of props.additionalDeps ?? []) { + this.addDependency(dep); + } + new POCProjectFiles(this, props); + } + + public get readmeDetails(): POCReadmeDetails { + return { + pocDescription: this.pocProps.pocDescription ?? this.pocProps.pocName, + pocName: this.pocProps.pocName, + imagePath: `genai-quickstart-pocs-python/${this.pocProps.pocPackageName}/images/demo.gif`, + architectureImage: this.pocProps.readme?.pocGoal?.architectureImage ?? false, + }; + } + + postSynthesize() { + // Overriding the default postSynth to avoid every POC installing dependencies! + } +} + + +class POCProjectFiles extends Component { + private pocProps: StreamlitQuickStartPOCProps; + constructor(project: Project, props: StreamlitQuickStartPOCProps) { + super(project); + this.pocProps = props; + + } + /** + * Synthesize the project files + */ + public synthesize(): void { + if (!(this.pocProps.excludeFromReadmeManagement ?? false)) { + this.project.tryRemoveFile('README.md'); + new README(this.project, 'README.md', this.pocProps); + } + new HOWTO(this.project).synthesize(); + if (!this.pocProps.skipApp) { + new AppDotPy(this.project).synthesize(); + } + + } + +} + +class README extends TextFile { + constructor(scope: Project, id: string, props: StreamlitQuickStartPOCProps) { + const README_TEMPLATE = path.join(__dirname, 'resources', 'streamlit-readme.md'); + const readmeTemplate = fs.readFileSync(README_TEMPLATE, 'utf-8'); + const content = nunjucks.renderString(readmeTemplate, { + pocTitle: props.pocName, + pocOverview: props.pocDescription, + pocPath: `genai-quickstart-pocs-python/${props.pocPackageName}`, + additionalPrerequisits: props.readme?.additionalPrerequisits, + pocGoal: props.readme?.pocGoal, + fileWalkthrough: props.readme?.fileWalkthrough, + extraSteps: props.readme?.extraSteps, + finalText: props.readme?.finalText, + }); + super(scope, id, { + lines: content.split('\n'), + }); + } +} + + +class HOWTO extends SampleFile { + constructor(scope: Project) { + const HOWTO_TEMPLATE: string = path.join(__dirname, 'resources', 'streamlit-howto.md'); + const howtoTemplate = fs.readFileSync(HOWTO_TEMPLATE, 'utf-8'); + super(scope, 'HOWTO.md', { + contents: howtoTemplate, + }); + } +} + +class AppDotPy extends SampleFile { + constructor(scope: Project) { + const APP_TEMPLATE = path.join(__dirname, 'resources', 'streamlit-app.py'); + const appTemplate = fs.readFileSync(APP_TEMPLATE, 'utf-8'); + super(scope, 'app.py', { + contents: appTemplate, + }); + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..92c94b81 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,5 @@ +export class Hello { + public sayHello() { + return 'hello, world!'; + } +} \ No newline at end of file diff --git a/test/hello.test.ts b/test/hello.test.ts new file mode 100644 index 00000000..acbacd4d --- /dev/null +++ b/test/hello.test.ts @@ -0,0 +1,5 @@ +import { Hello } from '../src'; + +test('hello', () => { + expect(new Hello().sayHello()).toBe('hello, world!'); +}); \ No newline at end of file diff --git a/tsconfig.dev.json b/tsconfig.dev.json new file mode 100644 index 00000000..713e6224 --- /dev/null +++ b/tsconfig.dev.json @@ -0,0 +1,41 @@ +// ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". +{ + "compilerOptions": { + "alwaysStrict": true, + "declaration": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "inlineSourceMap": true, + "inlineSources": true, + "lib": [ + "es2019" + ], + "module": "CommonJS", + "noEmitOnError": false, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "strict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "stripInternal": true, + "target": "ES2019", + "rootDir": ".", + "sourceRoot": "." + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts", + "genai-quickstart-pocs-python/**/*", + "projenrc/**/*", + ".projenrc.ts", + "projenrc/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..acaefeb8 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,37 @@ +// ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". +{ + "compilerOptions": { + "rootDir": ".", + "outDir": "lib", + "alwaysStrict": true, + "declaration": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "inlineSourceMap": true, + "inlineSources": true, + "lib": [ + "es2019" + ], + "module": "CommonJS", + "noEmitOnError": false, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "strict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "stripInternal": true, + "target": "ES2019", + "sourceRoot": "." + }, + "include": [ + "src/**/*.ts", + "genai-quickstart-pocs-python/**/*", + "projenrc/**/*" + ], + "exclude": [] +}