├── .eslintrc.json ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── README_zh.md ├── app ├── api │ ├── auth │ │ ├── [...nextauth] │ │ │ └── route.ts │ │ └── session.ts │ └── chat │ │ └── route.ts ├── favicon.ico ├── globals.css ├── layout.tsx ├── login │ └── page.tsx ├── page.tsx └── providers.tsx ├── asset ├── image-4-1.png ├── image-4-2.png ├── image-4-3.png ├── image.png ├── image2.png ├── image3_1.png ├── image3_2.png ├── image3_3.png ├── image3_4.png ├── image3_5.png ├── image4.png ├── image5.png ├── image6.png ├── image6_0.png ├── image7-1.png ├── image7-2.png ├── image7-3.png ├── ml.alpha.24xlarge_tp8.csv ├── ml.beta.24xlarge_tp4.csv ├── ml.beta.24xlarge_tp8.csv └── open_artifacts_bedrock_en-cover.jpg ├── components.json ├── components ├── artifact-view.tsx ├── chat.tsx ├── code-view.tsx ├── side-view.tsx └── ui │ ├── alert.tsx │ ├── input.tsx │ ├── skeleton.tsx │ └── tabs.tsx ├── docker_files ├── Dockerfile ├── README.md └── test.js ├── lib ├── local-sandbox.ts └── utils.ts ├── next-auth.d.ts ├── next.config.mjs ├── package.json ├── pm2run.config.js ├── postcss.config.mjs ├── public ├── logo.svg ├── next.svg └── vercel.svg ├── tailwind.config.ts ├── tsconfig.json └── yarn.lock /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | workingdir 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* 131 | 132 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 133 | 134 | # dependencies 135 | /node_modules 136 | /.pnp 137 | .pnp.js 138 | .yarn/install-state.gz 139 | 140 | # testing 141 | /coverage 142 | 143 | # next.js 144 | /.next/ 145 | /out/ 146 | 147 | # production 148 | /build 149 | 150 | # misc 151 | .DS_Store 152 | *.pem 153 | 154 | # debug 155 | npm-debug.log* 156 | yarn-debug.log* 157 | yarn-error.log* 158 | 159 | # local env files 160 | .env*.local 161 | 162 | # vercel 163 | .vercel 164 | 165 | # typescript 166 | *.tsbuildinfo 167 | next-env.d.ts -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | 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. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT No Attribution 2 | 3 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 13 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 14 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 15 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open Artifacts for Amazon Bedrock 2 | [English](./README.md) | [中文](./README_zh.md) 3 | 4 | ## About Artifacts 5 | Artifacts is a new feature introduced by Anthropic that expands the way users interact with the Claude model. 6 | When users ask Claude to generate code snippets, text documents, or website designs, these artifacts appear in a dedicated window within their conversation. 7 | Users can view, edit, and build Claude's creations in real-time, seamlessly integrating Claude-generated content into their projects and workflows. 8 | 9 | ## Introduction to this Open Source Artifacts Project 10 | - This project uses [Vercel AI](https://sdk.vercel.ai/), an open-source large model application development framework for Next.js, utilizing Claude 3.5 on Amazon Bedrock, and draws inspiration from examples in [e2b](https://e2b.dev/docs) to recreate an open-source version of Anthropic's Artifacts UI functionality. It interacts with the Claude model through a code interceptor component, generating corresponding code, text, and design content, then executes and returns interactive results using a locally built sandbox image. 11 | - The main features currently include: 12 | 1. Support for Bedrock Claude 3.5 integration 13 | 2. Direct use of locally created docker images as sandboxes, ensuring data privacy and security, improving development convenience and execution performance. 14 | 3. Support HTML/JS frontend rendering, allowing generation of HTML/JS code that can be directly rendered in the browser and support real-time interaction. 15 | 4. Support multimodal capabilities, e.g., uploading spreadsheets screenshots, PDF screenshots, and generating code for data visualization analysis. 16 | 4. Support uploading CSV spreadsheets and generating code to read the file directly for data analysis. 17 | 5. Other features such as simple user login/logout, clearing context, copying and pasting to directly upload images, etc. 18 | 19 | 20 | ## Video Demo 21 | [![Video Demo](asset/open_artifacts_bedrock_en-cover.jpg)](https://youtu.be/KqqVYtA_X-8) 22 | ## Environment Preparation 23 | - Can be set up in a local Mac environment or on an Amazon EC2 instance (Amazon Linux 2023 is recommended), a CPU instance is sufficient, no GPU instance required 24 | 1. Install nodejs and yarn 25 | ```bash 26 | sudo yum install https://rpm.nodesource.com/pub_18.x/nodistro/repo/nodesource-release-nodistro-1.noarch.rpm -y 27 | sudo yum install nodejs -y --setopt=nodesource-nodejs.module_hotfixes=1 --nogpgcheck 28 | sudo npm install --global yarn 29 | ``` 30 | 2. Install & start docker (skip if already installed) 31 | ```bash 32 | sudo yum install docker -y 33 | sudo service docker start 34 | sudo chmod 666 /var/run/docker.sock 35 | ``` 36 | ## Usage Instructions 37 | ### 1. Configure docker image 38 | 1. Enter open_artifacts_for_bedrock/docker_files 39 | ```bash 40 | cd open_artifacts_for_bedrock/docker_files 41 | ``` 42 | 43 | 2. Open a terminal in this folder (containing Dockerfile) and run the following command to build the Docker image: 44 | ```bash 45 | docker build -t python3.10 . 46 | ``` 47 | This command will create a Docker image named python3.10. If you need to install a specific Python version or other dependencies, you can modify the Dockerfile. 48 | 49 | ### 2. Configure .env, set AK SK, and enable permissions 50 | 1. Create a .env file in the open_artifacts directory with the following content: 51 | The default username and password is admin/admin, can you can change them via setting in .env file. 52 | If you did not set the AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY, then you need to bind a IAM role to your EC2. 53 | ``` 54 | AWS_ACCESS_KEY_ID=******* 55 | AWS_SECRET_ACCESS_KEY=****** 56 | AWS_REGION=us-east-1 57 | PYTHON_DOCKER_IMAGE=python3.10 58 | MODEL_ID=anthropic.claude-3-5-sonnet-20240620-v1:0 59 | USERNAME= 60 | PASSWORD= 61 | ``` 62 | 63 | 2. (Optional) In case you want to use IAM role instead of AK/SK 64 | - IAM Role's permission 65 | Create a new IAM role with name artifacts-service-role and settings below: 66 | - Trusted entity type: AWS Service 67 | - Service: EC2 68 | - Use Case: EC2 - Allows EC2 instances to call AWS services on your behalf. 69 | 70 | Skip "Add permission" and create this role first. 71 | After the role is created, and then add permission by creating inline policy as below: 72 | ```json 73 | { 74 | "Version": "2012-10-17", 75 | "Statement": [ 76 | { 77 | "Sid": "VisualEditor0", 78 | "Effect": "Allow", 79 | "Action": [ 80 | "bedrock:*", 81 | ], 82 | "Resource": "*" 83 | } 84 | ] 85 | } 86 | ``` 87 | Finally, Bind this IAM instance profile (IAM Role) to your EC2 instance. 88 | 89 | 90 | 2. If running locally, execute the following. Upon successful execution, it will open the local UI port 3000. Access via http://localhost:3000 91 | ```bash 92 | yarn 93 | yarn dev 94 | ``` 95 | - If using on a cloud host, you need to open port 3000, access via http://ip:3000 96 | ```bash 97 | yarn dev -- -H 0.0.0.0 98 | ``` 99 | 100 | ## Demo 101 | ### Snake Game 102 | - Step by step prompt 103 | ``` 104 | 1. Create an automatic snake game, be cool and fancy 105 | 2. Change the background color to black 106 | 3. Add some fireworks background, etc. 107 | 4. Add a starry sky background image 108 | ``` 109 | ![alt text](asset/image.png) 110 | 111 | ### Solar System Simulation 112 | ``` 113 | make a threejs app of a space sim with gravity of a solar system with planets in a single web file. 114 | the planets should be orbiting around the sun. Add a light source to the sun and realistic random materials to each planet. Add orbit traces to all bodies. use cannonjs. Using top view. 115 | ``` 116 | ![alt text](asset/image2.png) 117 | 118 | ### Frontend webpage design,screenshot2code 119 | - Enter Prompt: 120 | ``` 121 | Create a cool and impressive sales dashboard page design using Tailwind CSS and React JS. The dashboard should display rankings for different platforms (JD.com, Taobao, VIP.com) including product category rankings, store rankings, GMV (Gross Merchandise Value), number of orders, and other relevant metrics 122 | ``` 123 | 124 | - And we can see the result 125 | ![alt text](asset/image7-1.png) 126 | - Let's give it an image as reference 127 | ![alt text](asset/image7-2.png) 128 | copy the image and past it into the chat inputbox. 129 | Enter prompt 130 | ``` 131 | please use the style in attached image to refine the page 132 | ``` 133 | 134 | - Now you can see the new style is pretty cool and very closed to the reference style. 135 | ![alt text](asset/image7-3.png) 136 | 137 | 138 | ### Data Visualization Analysis (Visual QA) 139 | #### case 1 140 | - Upload image (You can also directly copy and paste the image into chat input box) 141 | ![alt text](asset/image3_1.png) 142 | 143 | - Prompt 144 | ``` 145 | analyze and plot the data in the image 146 | ``` 147 | 148 | - Result 149 | ![alt text](asset/image3_5.png) 150 | 151 | #### case 2 152 | - Upload images 1, 2, 3 153 | ![alt text](asset/image3_1.png) 154 | ![alt text](asset/image3_2.png) 155 | ![alt text](asset/image3_3.png) 156 | 157 | - Prompt 158 | ``` 159 | You are a professional data analyst. The first image is performance test data for ml.alpha.24xlarge with tp=8, the second image is for ml.beta.24xlarge with tp=4, and the third image is for ml.beta.24xlarge with tp=8. Please compare and analyze the data in these 3 images, and create a visualized data analysis comparison chart, focusing on the relationship between concurrency, throughput, and latency. 160 | ``` 161 | 162 | - Result 163 | ![alt text](asset/image3_4.png) 164 | 165 | ### Data Visualization Analysis (File QA) 166 | - Download CSV files,and upload in one shot 167 | * [ml.alpha.24xlarge_tp8.csv](asset/ml.alpha.24xlarge_tp8.csv) 168 | * [ml.beta.24xlarge_tp4.csv](asset/ml.beta.24xlarge_tp4.csv) 169 | * [ml.beta.24xlarge_tp8.csv](asset/ml.beta.24xlarge_tp8.csv) 170 | 171 | - Step by step Prompt 172 | 1. 173 | ``` 174 | You are a professional data analyst. The first image is performance test data for ml.alpha.24xlarge with tp=8, the second image is for ml.beta.24xlarge with tp=4, and the third image is for ml.beta.24xlarge with tp=8. Please compare and analyze the data in these 3 images, and create a visualized data analysis comparison chart, focusing on the relationship between concurrency, throughput, and latency. 175 | ``` 176 | 2. 177 | ``` 178 | Please continue analyzing. 179 | ``` 180 | 3. If you encounter excution error, you just need to copy and past the error log to the chat input box, and the AI will continue to fix it. 181 | 182 | - Result 183 | * ![alt text](asset/image-4-1.png) 184 | * ![alt text](asset/image-4-2.png) 185 | * ![alt text](asset/image-4-3.png) 186 | 187 | ### Generate Architecture Diagram 188 | ``` 189 | create an web server architecture diagram using aws loadbalancer, ec2, rds 190 | ``` 191 | ``` 192 | add api gateway between lb and web servers, and put the servers in vpc 193 | ``` 194 | ``` 195 | it errors : No module named 'diagrams.aws.apigateway'\n 196 | ``` 197 | ![alt text](asset/image5.png) 198 | 199 | ### Architecture Conversion Between Different Clouds 200 | - Prompt 201 | ``` 202 | explain the architecture in the image, and alternate all the services to aws services accordingly and draw aws architecture diagram 203 | ``` 204 | - Upload image 205 | ![alt text](asset/image6_0.png) 206 | - Result 207 | ![alt text](asset/image6.png) 208 | 209 | ## Others 210 | ### FAQ 211 | 1. How to ensure all dependencies for running code are met? 212 | You can check the error messages returned by the frontend code execution page to see if any modules are missing. If missing, you can modify the docker_files/Dockerfile file, add the corresponding packages, and then build: 213 | ```bash 214 | docker build -t python3.10 . 215 | ``` 216 | 217 | 2. Running in the background with PM2 218 | ```bash 219 | #install pm2 220 | sudo yarn global add pm2 221 | pm2 start pm2run.config.js 222 | ``` 223 | - Below are more commands for managing artifacts with PM2: 224 | ```bash 225 | pm2 list 226 | pm2 stop artifacts 227 | pm2 restart artifacts 228 | pm2 delete artifacts 229 | ``` 230 | 231 | 232 | -------------------------------------------------------------------------------- /README_zh.md: -------------------------------------------------------------------------------- 1 | # Open Artifacts for Amazon Bedrock 2 | [English](./README.md) | [中文](./README_zh.md) 3 | 4 | ## 关于Artifacts 5 | Artifacts是Anthropic推出的一项新功能,它扩展了用户与Claude模型的互动方式。 6 | 当用户要求Claude生成代码片段、文本文档或网站设计等内容时,这些工件会出现在他们对话的专用窗口中。 7 | 可以实时查看、编辑和构建Claude的创作,将claude生成的内容无缝集成到他们的项目和工作流程中 8 | 9 | ## 本开源Artifacts项目简介 10 | - 本项目采用 [Vercel AI](https://sdk.vercel.ai/) 一个next.js开源的大模型应用开发框架,使用Amazon Bedrock上的Claude 3.5,并借鉴了[e2b](https://e2b.dev/docs) 中的example,复刻一个开源版本的Anthropic的Artifacts UI功能,它通过code intereptor组件与Claude模型交互,生成相应的代码,文本及设计内容,然后通过本地build的sandbox镜像执行并返回交互式的结果。 11 | - 目前主要功能特点如下: 12 | 1. 支持Bedrock Claude 3.5接入 13 | 2. 直接使用本地自己制作的docker image作为sandbox,保证数据隐私和安全,提高开发便捷性,执行性能。 14 | 3. 新增支持HTML/JS 前端渲染功能,可以生成HTML/JS代码,直接在浏览器渲染,并可以支持实时交互。 15 | 4. 新增图片上传加入多模态能力,例如可以上传excel表格,pdf截图,并生成代码做数据可视化分析。 16 | 5. 其他小功能,例如清除上下文,复制粘贴直接上传图片等 17 | 18 | ## 视频Demo 19 | * 公众号 [复刻Open Artifacts](https://mp.weixin.qq.com/s/HsMAkLHsWNrkfsp9N11bVA) 20 | * Youtube English version 21 | [![Video Demo](asset/open_artifacts_bedrock_en-cover.jpg)](https://youtu.be/KqqVYtA_X-8) 22 | 23 | 24 | ## 环境准备 25 | - 可以在本地mac环境或者Amazon EC2实例(推荐Amazon Linux 2023),CPU机型即可,无需GPU实例 26 | 1. 安装nodejs和yarn 27 | ```bash 28 | sudo yum install https://rpm.nodesource.com/pub_18.x/nodistro/repo/nodesource-release-nodistro-1.noarch.rpm -y 29 | sudo yum install nodejs -y --setopt=nodesource-nodejs.module_hotfixes=1 --nogpgcheck 30 | sudo npm install --global yarn 31 | ``` 32 | 2. 安装 &启动 docker(如有可调过) 33 | ```bash 34 | sudo yum install docker -y 35 | sudo service docker start 36 | sudo chmod 666 /var/run/docker.sock 37 | ``` 38 | ## 使用说明 39 | ### 1. 配置docker image 40 | 1. 进入open_artifacts_for_bedrock/docker_files 41 | ```bash 42 | cd open_artifacts_for_bedrock/docker_files 43 | ``` 44 | 45 | 2. 在本文件夹下(包含 Dockerfile) 的目录中打开终端,运行以下命令来构建 Docker 镜像: 46 | ```bash 47 | docker build -t python3.10 . 48 | ``` 49 | 这个命令会创建一个名为 python3.10 的 Docker 镜像。如果需要安装某个特定的 Python 版本,或者需要安装其他依赖,则可以在Dockerfile 中进行修改。 50 | 51 | ### 2. 配置.env, 设置AK SK,并开通权限 52 | 1. 在open_artifacts目录下创建一个:.env文件,内容如下(请在环境变量中配置用户密码,默认用户密码admin/admin): 53 | 如果没有AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY, 则可以通过配置对应的ec2 service role来获取权限 54 | 55 | ``` 56 | AWS_ACCESS_KEY_ID=******* 57 | AWS_SECRET_ACCESS_KEY=****** 58 | AWS_REGION=us-east-1 59 | PYTHON_DOCKER_IMAGE=python3.10 60 | MODEL_ID=anthropic.claude-3-5-sonnet-20240620-v1:0 61 | USERNAME= 62 | PASSWORD= 63 | 64 | 2. (可选) 如果您想使用 IAM 角色而不是 AK/SK 65 | IAM 角色的权限 66 | 创建一个名为 artifacts-service-role 的新 IAM 角色,设置如下: 67 | 可信实体类型:AWS 服务 68 | 服务:EC2 69 | 使用案例:EC2 - 允许 EC2 实例代表您调用 AWS 服务。 70 | 跳过"添加权限",先创建这个角色。 71 | 角色创建后,通过创建内联策略添加权限,如下所示: 72 | ```json 73 | { 74 | "Version": "2012-10-17", 75 | "Statement": [ 76 | { 77 | "Sid": "VisualEditor0", 78 | "Effect": "Allow", 79 | "Action": [ 80 | "bedrock:*", 81 | ], 82 | "Resource": "*" 83 | } 84 | ] 85 | } 86 | ``` 87 | 最后,将此 IAM 实例配置文件(IAM 角色)绑定到您的 EC2 实例。 88 | 89 | 3. 如果在本地启用执行,执行成功会打开本地3000的ui端口. 通过http://localhost:3000访问 90 | ```bash 91 | yarn 92 | yarn dev 93 | ``` 94 | - 如果在云端主机使用,需要打开3000端口,通过http://ip:3000访问 95 | ```bash 96 | yarn dev -- -H 0.0.0.0 97 | ``` 98 | 99 | ## 效果演示 100 | ### 贪吃蛇 101 | ``` 102 | 1. 创建一个自动的贪吃蛇游戏, be cool and fancy 103 | 2. 更换背景颜色为黑色 104 | 3. 放一些烟花背景等 105 | 4. 增加星空背景图 106 | ``` 107 | ![alt text](asset/image.png) 108 | 109 | ### 模拟太阳系 110 | ``` 111 | make a threejs app of a space sim with gravity of a solar system with planets in a single web file. 112 | the planets should be orbiting around the sun. Add a light source to the sun and realistic random materials to each planet. Add orbit traces to all bodies. use cannonjs. Using top view. 113 | ``` 114 | ![alt text](asset/image2.png) 115 | 116 | ### 页面设计,screenshot2code 117 | - 提示词: 118 | ``` 119 | Create a cool and impressive sales dashboard page design using Tailwind CSS and React JS. The dashboard should display rankings for different platforms (JD.com, Taobao, VIP.com) including product category rankings, store rankings, GMV (Gross Merchandise Value), number of orders, and other relevant metrics 120 | ``` 121 | * 中文 122 | ``` 123 | 使用tailwind css, react js, 做一个酷炫销售dashboard的页面设计,分不同平台(京东、淘宝、唯品会)的商品类目排名,店铺排名,GMV,订单数等 124 | ``` 125 | 126 | - 右侧窗口可以看到制作出的设计界面 127 | ![alt text](asset/image7-1.png) 128 | - 以上的效果还比较简陋,我们给他一张设计稿图作为参考,这样artifact做出的设计图更加准确 129 | ![alt text](asset/image7-2.png) 130 | 复制图片到聊天窗,并添加新提示 131 | ``` 132 | please use the style in attached image to refine the page 133 | ``` 134 | * 中文 135 | ``` 136 | 参考这个图的样式进行修改 137 | ``` 138 | - 这次可以看到右侧窗口输出的页面,效果更加接近参考图 139 | ![alt text](asset/image7-3.png) 140 | 141 | 142 | ### 数据可视化分析(图片分析) 143 | #### case 1 144 | - 上传图片1(可复制并粘贴进对话框) 145 | ![alt text](asset/image3_1.png) 146 | 147 | - 提示词 148 | ``` 149 | analyze and plot the data in the image 150 | ``` 151 | 152 | - Result 153 | ![alt text](asset/image3_5.png) 154 | 155 | 156 | #### case 2 157 | - 上传图片1,2,3 158 | ![alt text](asset/image3_1.png) 159 | ![alt text](asset/image3_2.png) 160 | ![alt text](asset/image3_3.png) 161 | 162 | - 提示词 163 | ``` 164 | 你是一名专业的数据分析师,第1张图是ml.alpha.24xlarge,在tp=8的性能测试数据,第2张图是ml.beta.24xlarge,在tp=4的性能测试数据,第3张图是ml.beta.24xlarge,在tp=8的性能测试数据。请对比分析这3张图中的数据,并绘制可视化的数据分析对比图,重点关注concurrency 跟 throughput,latency的关系 165 | ``` 166 | 167 | - 结果 168 | ![alt text](asset/image3_4.png) 169 | 170 | 171 | ### python 数据可视化分析(上传csv文件分析) 172 | - 下载以下文件到本地,并从聊天窗口同时上传3个csv文件 173 | * [ml.alpha.24xlarge_tp8.csv](asset/ml.alpha.24xlarge_tp8.csv) 174 | * [ml.beta.24xlarge_tp4.csv](asset/ml.beta.24xlarge_tp4.csv) 175 | * [ml.beta.24xlarge_tp8.csv](asset/ml.beta.24xlarge_tp8.csv) 176 | 177 | - 提示词 178 | 1. 179 | ``` 180 | 你是一名专业的数据分析师,第1张图是ml.alpha.24xlarge,在tp=8的性能测试数据,第2张图是ml.beta.24xlarge,在tp=4的性能测试数据,第3张图是ml.beta.24xlarge,在tp=8的性能测试数据。请对比分析这3张图中的数据,并绘制可视化的数据分析对比图,重点关注concurrency 跟 throughput,latency的关系 181 | ``` 182 | 2. 183 | ``` 184 | 请继续分析 185 | ``` 186 | 3. 如果碰到执行错误,则将错误信息复制进入输入框,再次点击执行 187 | 188 | - 最终结果 189 | * ![alt text](asset/image-4-1.png) 190 | * ![alt text](asset/image-4-2.png) 191 | * ![alt text](asset/image-4-3.png) 192 | 193 | ### 生成架构图 194 | ``` 195 | create an web server architecture diagram using aws loadbalancer, ec2, rds 196 | ``` 197 | ``` 198 | add api gateway between lb and web servers, and put the servers in vpc 199 | ``` 200 | ``` 201 | it errors : No module named 'diagrams.aws.apigateway'\n 202 | ``` 203 | ![alt text](asset/image5.png) 204 | 205 | ### 不同云只之间的架构转换 206 | - 上传图片 207 | ![alt text](asset/image6_0.png) 208 | 209 | - 提示词 210 | ``` 211 | explain the architecture in the image, and alternate all the services to aws services accordingly and draw aws architecture diagram 212 | ``` 213 | 214 | - 结果 215 | ![alt text](asset/image6.png) 216 | 217 | ## 其他 218 | ### FAQ 219 | 1. 如何保证运行代码的依赖都能满足? 220 | 可以根据前端代码执行页面返回的报错信息,查看是否缺少module,如果缺少可以修改docker_files/Dockerfile文件,添加对应的包,然后build即可 221 | ```bash 222 | docker build -t python3.10 . 223 | ``` 224 | 225 | 2. 使用PM2后台运行 226 | ```bash 227 | #install pm2 228 | sudo yarn global add pm2 229 | pm2 start pm2run.config.js 230 | ``` 231 | - 以下是其他的管理命令: 232 | ```bash 233 | pm2 list 234 | pm2 stop artifacts 235 | pm2 restart artifacts 236 | pm2 delete artifacts 237 | ``` 238 | 239 | -------------------------------------------------------------------------------- /app/api/auth/[...nextauth]/route.ts: -------------------------------------------------------------------------------- 1 | import NextAuth from "next-auth" 2 | import CredentialsProvider from "next-auth/providers/credentials" 3 | 4 | const handler = NextAuth({ 5 | providers: [ 6 | CredentialsProvider({ 7 | name: 'Credentials', 8 | credentials: { 9 | username: { label: "Username", type: "text" }, 10 | password: { label: "Password", type: "password" } 11 | }, 12 | async authorize(credentials, req) { 13 | // 获取环境变量中的用户名和密码列表 14 | const usernames = (process.env.USERNAME ?? 'admin').split(','); 15 | const passwords = (process.env.PASSWORD ?? 'admin').split(','); 16 | 17 | // 检查提供的凭证是否匹配任何用户名和密码对 18 | const isValidCredentials = usernames.some((username, index) => 19 | credentials?.username === username.trim() && 20 | credentials?.password === passwords[index].trim() 21 | ); 22 | 23 | if (isValidCredentials) { 24 | return { id: "1", name: credentials?.username, email: `${credentials?.username}@example.com` } 25 | } else { 26 | return null 27 | } 28 | } 29 | }) 30 | ], 31 | pages: { 32 | signIn: '/login', 33 | }, 34 | }) 35 | 36 | export { handler as GET, handler as POST } 37 | -------------------------------------------------------------------------------- /app/api/auth/session.ts: -------------------------------------------------------------------------------- 1 | 'use server' 2 | import { getSession } from 'next-auth/react' 3 | export default async function handler(req, res) { 4 | const session = await getSession({ req }) 5 | if (session) { 6 | session.user = { ...session.user, name: req.body.username } 7 | await req.session.save() 8 | res.status(200).json({ message: 'Session updated' }) 9 | } else { 10 | res.status(401).json({ message: 'Unauthorized' }) 11 | } 12 | } -------------------------------------------------------------------------------- /app/api/chat/route.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | import { 3 | type CoreMessage, 4 | type ImagePart, 5 | type TextPart, 6 | type UserContent, 7 | StreamingTextResponse, 8 | StreamData, 9 | streamText, 10 | tool 11 | } from 'ai' 12 | // import { anthropic } from '@ai-sdk/anthropic' 13 | import { bedrock,createAmazonBedrock} from '@ai-sdk/amazon-bedrock'; 14 | import { 15 | runPython, 16 | runJs 17 | } from '@/lib/local-sandbox' 18 | import {type FileData} from '@/components/chat'; 19 | 20 | import * as path from 'path'; 21 | import * as fs from 'fs'; 22 | import { fileURLToPath } from 'url'; 23 | import { dirname } from 'path'; 24 | 25 | const __filename = fileURLToPath(import.meta.url); 26 | const __dirname = dirname(__filename); 27 | // 获取上两级目录的路径 28 | const twoLevelsUp = path.resolve(__dirname, '..', '..','..'); 29 | 30 | export interface ServerMessage { 31 | role: 'user' | 'assistant' | 'function'; 32 | content: string; 33 | } 34 | 35 | interface ToolResult { 36 | /** 37 | ID of the tool call. This ID is used to match the tool call with the tool result. 38 | */ 39 | toolCallId: string; 40 | /** 41 | Name of the tool that was called. 42 | */ 43 | toolName: NAME; 44 | /** 45 | Arguments of the tool call. This is a JSON-serializable object that matches the tool's input schema. 46 | */ 47 | args: ARGS; 48 | /** 49 | Result of the tool call. This is the result of the tool's execution. 50 | */ 51 | result: RESULT; 52 | } 53 | 54 | type initMessages ={ 55 | role: 'user' | 'assistant'; 56 | content: string; 57 | toolInvocations?: Array>; 58 | }; 59 | 60 | function saveCSVToFile(fileData: FileData, outputDir: string): Promise { 61 | return new Promise((resolve, reject) => { 62 | const fileName = `${fileData.name}`; 63 | const filePath = path.join(outputDir, fileName); 64 | 65 | fs.writeFile(filePath, fileData.content, 'utf8', (err) => { 66 | if (err) { 67 | reject(err); 68 | } else { 69 | console.log(`save file:${filePath}`) 70 | resolve(filePath); 71 | } 72 | }); 73 | }); 74 | } 75 | 76 | function saveXLSXToFile(fileData: FileData, outputDir: string): Promise { 77 | return new Promise((resolve, reject) => { 78 | // Convert base64 to binary 79 | const binaryData = Buffer.from(fileData.content, 'base64'); 80 | const fileName = `${fileData.name}`; 81 | const filePath = path.join(outputDir, fileName); 82 | // Write the file 83 | fs.writeFile(filePath, binaryData, (err) => { 84 | if (err) { 85 | reject(err); 86 | } else { 87 | console.log(`save file:${filePath}`) 88 | resolve(filePath); 89 | } 90 | }); 91 | }); 92 | } 93 | 94 | 95 | export async function POST(req: Request) { 96 | 97 | const { messages, userID, data }: { messages: CoreMessage[], userID: string, data:string } = await req.json() 98 | 99 | //workingDirPath = app/workingdir/{userID} 100 | const workingDirPath = path.join(twoLevelsUp,'workingdir', userID); 101 | 102 | if (!fs.existsSync(workingDirPath)) { 103 | fs.mkdirSync(workingDirPath, { recursive: true }); 104 | } 105 | let llmModel; 106 | if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY){ 107 | console.log('using bedrock client specified from env') 108 | // llmModel = bedrock(process.env.MODEL_ID || 'anthropic.claude-3-5-sonnet-20240620-v1:0'); 109 | const bedrockClient = createAmazonBedrock({ 110 | region: 'us-east-1', 111 | accessKeyId: process.env.AWS_ACCESS_KEY_ID, 112 | secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, 113 | }); 114 | llmModel = bedrockClient(process.env.MODEL_ID || 'anthropic.claude-3-5-sonnet-20240620-v1:0'); 115 | }else{ 116 | console.log('using default bedrock client') 117 | //use default credentials from the ec2 role or aws credentials 118 | const bedrockClient = new createAmazonBedrock({bedrockOptions:{ 119 | region: 'us-east-1', 120 | }}); 121 | llmModel = bedrockClient(process.env.MODEL_ID || 'anthropic.claude-3-5-sonnet-20240620-v1:0'); 122 | } 123 | 124 | const initialMessagesDraft = messages.slice(0, -1) as CoreMessage []; 125 | 126 | //to workround the issue that the content is empty 127 | const initialMessages = initialMessagesDraft.map((it) => ({ 128 | ...it, 129 | content: it.content||'## Result:', 130 | })); 131 | 132 | const currentMessage = messages[messages.length - 1]; 133 | const fileData = data?JSON.parse(data):null; 134 | let imageData : string []= []; 135 | let textFileName : string []= []; 136 | if (fileData&& fileData.length> 0) { 137 | fileData.map(async (it:FileData) => { 138 | if (it.type === 'image') { 139 | imageData.push(it.content); 140 | }else if (it.type === 'csv') { 141 | textFileName.push(it.name); 142 | const savedFilePath = await saveCSVToFile(it, workingDirPath); 143 | console.log(`CSV file saved to: ${savedFilePath}`); 144 | }else if (it.type === 'xlsx') { 145 | textFileName.push(it.name); 146 | const savedFilePath = await saveXLSXToFile(it, workingDirPath); 147 | console.log(`XLSX file saved to: ${savedFilePath}`); 148 | } else if (it.type !== 'text') { 149 | console.log(`${it.type} not supported yet`) 150 | } 151 | }) 152 | } 153 | const fileMessages = imageData.length>0? 154 | (imageData as []).map(it => ({ type: 'image', image: it})) as ImagePart[]: 155 | (textFileName.length>0 ? textFileName.map(it => ({ type: 'text', text: `Here is user's uploaded file name:${it}`})) as TextPart[]:[]) 156 | 157 | let userContent; 158 | let newMessages; 159 | if (currentMessage.role === 'user'){ 160 | userContent = [ 161 | { type: 'text', text: currentMessage.content as string }, 162 | ...fileMessages 163 | ] 164 | newMessages =[ 165 | ...initialMessages, 166 | { 167 | role: 'user', 168 | content: userContent as UserContent, 169 | }, 170 | ]; 171 | }else{ 172 | newMessages = messages; 173 | } 174 | 175 | 176 | //only pass the last 3 rounds messages 177 | newMessages = newMessages.slice(-7) 178 | 179 | console.log('newMessages:',newMessages) 180 | 181 | // console.log(newMessages) 182 | const streamData: StreamData = new StreamData() 183 | 184 | const result = await streamText({ 185 | // experimental_toolCallStreaming: true, 186 | model: llmModel, 187 | temperature:0.5, 188 | tools: { 189 | runPython: tool({ 190 | description: 'Runs Python code. such as data analysis, data exploration, math,etc', 191 | parameters: z.object({ 192 | title: z.string().describe('Short title (5 words max) of the artifact.'), 193 | description: z.string().describe('Short description (10 words max) of the artifact.'), 194 | code: z.string().describe('The code to run in its own context'), 195 | }), 196 | async execute({ code }) { 197 | streamData.append({ 198 | tool: 'runPython', 199 | state: 'running', 200 | }) 201 | const execOutput = await runPython(userID, code) 202 | const stdout = execOutput.logs.stdout 203 | const stderr = execOutput.logs.stderr 204 | const runtimeError = execOutput.error 205 | const results = execOutput.results 206 | console.log(`stdout:${stdout}`); 207 | streamData.append({ 208 | tool: 'runPython', 209 | stdout:stdout, 210 | state: 'complete', 211 | }) 212 | return { 213 | stdout, 214 | stderr, 215 | runtimeError, 216 | cellResults: results, 217 | } 218 | }, 219 | }), 220 | runJs: tool({ 221 | description: 'Runs HTML or Javascript code.', 222 | parameters: z.object({ 223 | title: z.string().describe('Short title (5 words max) of the artifact.'), 224 | description: z.string().describe('Short description (10 words max) of the artifact.'), 225 | code: z.string().describe('The code to run. can be a html and js code'), 226 | }), 227 | async execute({ code }) { 228 | // console.log(code) 229 | streamData.append({ 230 | tool: 'runJs', 231 | state: 'running', 232 | }) 233 | const execOutput = await runJs(userID, code) 234 | const stdout = execOutput.logs.stdout 235 | const stderr = execOutput.logs.stderr 236 | const runtimeError = execOutput.error 237 | const results = execOutput.results 238 | 239 | streamData.append({ 240 | tool: 'runJs', 241 | stdout:stdout, 242 | state: 'complete', 243 | }) 244 | // console.log(data) 245 | return { 246 | stdout, 247 | stderr, 248 | runtimeError, 249 | cellResults: results, 250 | } 251 | }, 252 | }), 253 | }, 254 | toolChoice: 'auto', 255 | system: ` 256 | You are a skilled Python and Javascript developer. 257 | You are also expert of data science and data analysis, and you are also expert of solution architecture of AWS, Google Cloud, Azure, etc. 258 | You are very familiar with the following tools and libraries: 259 | For Python: 260 | 261 | pandas, numpy, matplotlib, seaborn, scikit-learn, diagrams, sympy etc. 262 | 263 | 264 | For JavaScript: 265 | 266 | d3, react, canvas, threejs, cannonjs, etc. 267 | 268 | 269 | You have the ability to choose the appropriate tools and run Python or JavaScript code to solve the user's task. Code for each programming language runs in its own context and can reference previous definitions and variables. 270 | Your code will be run in a seperate sandbox, so you don't write the code that contains code to read the data or file locally. 271 | Here is extra guidance that help you to prevent bugs: 272 | 273 | 1. when you use matplotlib to plot a chart, you should not generate code "plt.style.use('seaborn')", because it will errors, you can use plt.style.use('ggplot') instead. 274 | 2. when you use matplotlib to plot a chart, to add chinese font, you should add the following code before plotting: 275 | 276 | plt.rcParams['font.sans-serif'] = ['WenQuanYi Micro Hei'] # 使用文泉驿微米黑 277 | plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 278 | 279 | 280 | `, 281 | onFinish() { 282 | streamData.close(); 283 | }, 284 | abortSignal: req.signal, 285 | messages:newMessages as CoreMessage[], 286 | }) 287 | 288 | // const stream = result.toAIStream({ 289 | // async onFinal() { 290 | // await streamData.close() 291 | // } 292 | // }) 293 | 294 | // return new StreamingTextResponse(stream, {}, streamData); 295 | // console.log(streamData) 296 | return result.toDataStreamResponse({data:streamData}); 297 | } 298 | -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/app/favicon.ico -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer base { 6 | :root { 7 | /* --background: 32 100% 95%; */ 8 | --background: 0 0 100%; 9 | --foreground: 222.2 84% 4.9%; 10 | 11 | --card: 0 0% 100%; 12 | --card-foreground: 222.2 84% 4.9%; 13 | 14 | --popover: 0 0% 100%; 15 | --popover-foreground: 222.2 84% 4.9%; 16 | 17 | --primary: 222.2 47.4% 11.2%; 18 | --primary-foreground: 210 40% 98%; 19 | 20 | --secondary: 210 40% 96.1%; 21 | --secondary-foreground: 222.2 47.4% 11.2%; 22 | 23 | --muted: 210 40% 96.1%; 24 | --muted-foreground: 215.4 16.3% 46.9%; 25 | 26 | --accent: 210 40% 96.1%; 27 | --accent-foreground: 222.2 47.4% 11.2%; 28 | 29 | --destructive: 0 84.2% 60.2%; 30 | --destructive-foreground: 210 40% 98%; 31 | 32 | --border: 214.3 31.8% 91.4%; 33 | --input: 214.3 31.8% 91.4%; 34 | --ring: 30, 100%, 50%; 35 | 36 | --radius: 0.5rem; 37 | } 38 | 39 | .dark { 40 | --background: 222.2 84% 4.9%; 41 | --foreground: 210 40% 98%; 42 | 43 | --card: 222.2 84% 4.9%; 44 | --card-foreground: 210 40% 98%; 45 | 46 | --popover: 222.2 84% 4.9%; 47 | --popover-foreground: 210 40% 98%; 48 | 49 | --primary: 210 40% 98%; 50 | --primary-foreground: 222.2 47.4% 11.2%; 51 | 52 | --secondary: 217.2 32.6% 17.5%; 53 | --secondary-foreground: 210 40% 98%; 54 | 55 | --muted: 217.2 32.6% 17.5%; 56 | --muted-foreground: 215 20.2% 65.1%; 57 | 58 | --accent: 217.2 32.6% 17.5%; 59 | --accent-foreground: 210 40% 98%; 60 | 61 | --destructive: 0 62.8% 30.6%; 62 | --destructive-foreground: 210 40% 98%; 63 | 64 | --border: 217.2 32.6% 17.5%; 65 | --input: 217.2 32.6% 17.5%; 66 | --ring: 212.7 26.8% 83.9%; 67 | } 68 | } 69 | 70 | @layer base { 71 | * { 72 | @apply border-border; 73 | } 74 | body { 75 | @apply bg-[#fff3e6] text-foreground; 76 | } 77 | } -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from 'next' 2 | import { Inter } from 'next/font/google' 3 | import './globals.css' 4 | import { Providers } from './providers' 5 | const inter = Inter({ subsets: ['latin'] }) 6 | 7 | export const metadata: Metadata = { 8 | title: 'Open Artifacts', 9 | description: 'Generated by create next app', 10 | } 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: Readonly<{ 15 | children: React.ReactNode; 16 | }>) { 17 | return ( 18 | 19 | 20 | {children} 21 | 22 | 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /app/login/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useState } from 'react' 4 | import { signIn } from 'next-auth/react' 5 | import { useRouter } from 'next/navigation' 6 | import { Loader2, LogIn, AlertCircle } from 'lucide-react' 7 | 8 | export default function Login() { 9 | const [username, setUsername] = useState('') 10 | const [password, setPassword] = useState('') 11 | const [isLoading, setIsLoading] = useState(false) 12 | const [error, setError] = useState('') 13 | const router = useRouter() 14 | 15 | const handleSubmit = async (e: React.FormEvent) => { 16 | e.preventDefault() 17 | setIsLoading(true) 18 | setError('') 19 | 20 | const result = await signIn('credentials', { 21 | username, 22 | password, 23 | redirect: false, 24 | }) 25 | 26 | if (result?.error) { 27 | setError('Access denied. Please check your credentials.') 28 | setIsLoading(false) 29 | } else { 30 | // Store the username in the session 31 | await fetch('/api/auth/session', { 32 | method: 'POST', 33 | headers: { 'Content-Type': 'application/json' }, 34 | body: JSON.stringify({ username }), 35 | }) 36 | console.log(result); 37 | router.push('/') 38 | } 39 | } 40 | 41 | return ( 42 |
43 |
44 |

Open Arifacts for Bedrock

45 |
46 |
47 |
48 | 49 | setUsername(e.target.value)} 55 | required 56 | /> 57 |
58 |
59 | 60 | setPassword(e.target.value)} 66 | required 67 | /> 68 |
69 | {error && ( 70 |
71 | 72 | {error} 73 |
74 | )} 75 |
76 | 93 |
94 |
95 |
96 |
97 |
98 | ) 99 | } 100 | -------------------------------------------------------------------------------- /app/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useEffect } from 'react' 4 | import { useSession,signOut } from 'next-auth/react' 5 | import { useRouter } from 'next/navigation' 6 | import Image from 'next/image' 7 | import { useChat } from 'ai/react' 8 | import type { 9 | Message, 10 | } from '@ai-sdk/ui-utils'; 11 | import { Chat } from '@/components/chat' 12 | import { SideView } from '@/components/side-view' 13 | import { LogOut } from 'lucide-react' 14 | 15 | export default function Home() { 16 | const { data: session, status } = useSession() 17 | const router = useRouter() 18 | useEffect(() => { 19 | if (status === 'unauthenticated') { 20 | router.push('/login') 21 | } 22 | }, [status, router]) 23 | const handleLogout = async () => { 24 | await signOut({ callbackUrl: '/login' }) 25 | } 26 | const userID = session?.user?.name || 'default-user-id' 27 | 28 | const { messages, setMessages, reload, input,isLoading, setInput, append, handleInputChange, handleSubmit, data ,stop} = useChat({ 29 | api: '/api/chat', 30 | keepLastMessageOnError: true, 31 | body: { userID }, 32 | // onResponse: (response: Response) => { 33 | // console.log('Received response from server:', response) 34 | // }, 35 | // onFinish: (message: Message) => { 36 | // console.log('Finished streaming message:', message) 37 | // }, 38 | 39 | }) 40 | 41 | // For simplicity, we care only about the latest message that has a tool invocation 42 | const latestMessageWithToolInvocation = [...messages].reverse().find(message => message.toolInvocations && message.toolInvocations.length > 0) 43 | // Get the latest tool invocation 44 | const latestToolInvocation = latestMessageWithToolInvocation?.toolInvocations?.[0] 45 | 46 | const clearMessages = () => { 47 | setMessages([]); 48 | }; 49 | 50 | if (status === 'loading') { 51 | return
Loading...
52 | } 53 | 54 | if (!session) { 55 | return null 56 | } 57 | 58 | return ( 59 |
60 |
61 | logo 62 |
63 | 70 |
71 | 84 | 85 |
86 |
87 | ) 88 | } 89 | -------------------------------------------------------------------------------- /app/providers.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { SessionProvider } from "next-auth/react" 4 | 5 | export function Providers({ children }: { children: React.ReactNode }) { 6 | return {children} 7 | } -------------------------------------------------------------------------------- /asset/image-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image-4-1.png -------------------------------------------------------------------------------- /asset/image-4-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image-4-2.png -------------------------------------------------------------------------------- /asset/image-4-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image-4-3.png -------------------------------------------------------------------------------- /asset/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image.png -------------------------------------------------------------------------------- /asset/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image2.png -------------------------------------------------------------------------------- /asset/image3_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image3_1.png -------------------------------------------------------------------------------- /asset/image3_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image3_2.png -------------------------------------------------------------------------------- /asset/image3_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image3_3.png -------------------------------------------------------------------------------- /asset/image3_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image3_4.png -------------------------------------------------------------------------------- /asset/image3_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image3_5.png -------------------------------------------------------------------------------- /asset/image4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image4.png -------------------------------------------------------------------------------- /asset/image5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image5.png -------------------------------------------------------------------------------- /asset/image6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image6.png -------------------------------------------------------------------------------- /asset/image6_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image6_0.png -------------------------------------------------------------------------------- /asset/image7-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image7-1.png -------------------------------------------------------------------------------- /asset/image7-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image7-2.png -------------------------------------------------------------------------------- /asset/image7-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/image7-3.png -------------------------------------------------------------------------------- /asset/ml.alpha.24xlarge_tp8.csv: -------------------------------------------------------------------------------- 1 | instance_type,tp,concurrency,error_rate,prompt_token_count_mean,prompt_token_throughput,completion_token_count_mean,completion_token_throughput,latency_mean,latency_p50,latency_p95,latency_p99,transactions_per_minute 2 | ml.alpha.24xlarge,8,1,0,2287,169,513,37,13.4971,13.5,13.5,13.5,4 3 | ml.alpha.24xlarge,8,4,0,2287,617,513,138,14.80914,14.81,14.82,14.82,16 4 | ml.alpha.24xlarge,8,8,0,2287,1071,513,240,17.05541,17.06,17.06,17.06,28 5 | ml.alpha.24xlarge,8,16,0,2287,1668,513,374,21.90349,21.91,21.91,21.91,43 6 | ml.alpha.24xlarge,8,32,0,2287,2847,513,638,25.65906,25.66,25.68,25.69,74 7 | ml.alpha.24xlarge,8,48,0,2287,3534,513,792,30.98898,30.99,31.03,31.04,92 8 | ml.alpha.24xlarge,8,64,0,2287,3928,513,881,37.16361,37.16,37.23,37.23,103 -------------------------------------------------------------------------------- /asset/ml.beta.24xlarge_tp4.csv: -------------------------------------------------------------------------------- 1 | instance_type,tp,instance_count,concurrency,error_rate,prompt_token_count_mean,prompt_token_throughput,completion_token_count_mean,completion_token_throughput,latency_mean,latency_p50,latency_p95,latency_p99,transactions_per_minute 2 | ml.beta.24xlarge,4,1,1,0,2287,131,513,29,17.32409,17.32,17.32,17.32,3 3 | ml.beta.24xlarge,4,1,4,0,2287,499,513,112,18.26619,18.27,18.29,18.3,13 4 | ml.beta.24xlarge,4,1,8,0,2287,940,513,210,19.40982,19.4,19.45,19.45,24 5 | ml.beta.24xlarge,4,1,16,0,2287,1566,513,351,23.26109,23.25,23.34,23.34,40 6 | ml.beta.24xlarge,4,1,32,0,2287,2790,513,626,25.98325,26.13,26.2,26.2,73 7 | ml.beta.24xlarge,4,1,48,0,2287,3582,513,803,30.283,30.5,30.62,30.63,94 8 | ml.beta.24xlarge,4,1,64,0,2287,4242,513,951,34.1296,34.33,34.46,34.48,111 9 | ml.beta.24xlarge,4,1,80,0,2287,4656,513,1044,38.59657,39.01,39.24,39.25,122 10 | ml.beta.24xlarge,4,1,96,0,2287,5025,513,1127,42.95007,43.36,43.63,43.64,132 11 | ml.beta.24xlarge,4,1,128,0,2287,5167,513,1159,54.37339,56.18,56.57,56.61,135 -------------------------------------------------------------------------------- /asset/ml.beta.24xlarge_tp8.csv: -------------------------------------------------------------------------------- 1 | instance_type,tp,instance_count,concurrency,error_rate,prompt_token_count_mean,prompt_token_throughput,completion_token_count_mean,completion_token_throughput,latency_mean,latency_p50,latency_p95,latency_p99,transactions_per_minute 2 | ml.beta.24xlarge,8,1,1,0,2287,188,513,42,12.12687,12.13,12.13,12.13,4 3 | ml.beta.24xlarge,8,1,4,0,2287,679,513,152,13.45024,13.45,13.46,13.46,18 4 | ml.beta.24xlarge,8,1,8,0,2287,1150,513,258,15.88026,15.88,15.89,15.89,30 5 | ml.beta.24xlarge,8,1,16,0,2287,1742,513,390,20.97919,20.98,20.99,20.99,45 6 | ml.beta.24xlarge,8,1,32,0,2287,3035,513,680,24.062,24.07,24.1,24.1,79 7 | ml.beta.24xlarge,8,1,48,0,2287,3739,513,838,29.27134,29.29,29.33,29.34,97 8 | ml.beta.24xlarge,8,1,64,0,2287,4195,513,941,34.77165,34.78,34.85,34.87,109 9 | ml.beta.24xlarge,8,1,80,0,2287,4297,513,963,42.4233,42.43,42.54,42.56,112 10 | ml.beta.24xlarge,8,1,96,0,2287,4506,513,1010,48.53505,48.54,48.65,48.67,118 11 | ml.beta.24xlarge,8,1,112,0,2287,4620,513,1036,55.21066,55.2,55.35,55.36,121 -------------------------------------------------------------------------------- /asset/open_artifacts_bedrock_en-cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/open_artifacts_for_bedrock/6f30b62fca76274ddb6636b9a62cd4f195c37969/asset/open_artifacts_bedrock_en-cover.jpg -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/globals.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } -------------------------------------------------------------------------------- /components/artifact-view.tsx: -------------------------------------------------------------------------------- 1 | import { type ExecutionError, Result } from '@e2b/code-interpreter' 2 | import Image from 'next/image' 3 | import { Terminal } from 'lucide-react' 4 | 5 | import { 6 | Alert, 7 | AlertTitle, 8 | AlertDescription, 9 | } from '@/components/ui/alert' 10 | 11 | function LogsOutput({ stdout, stderr }: { 12 | stdout: string[] 13 | stderr: string[] 14 | }) { 15 | if (stdout.length === 0 && stderr.length === 0) return null 16 | 17 | return ( 18 |
19 | {stdout && stdout.length > 0 && stdout.map((out: string, index: number) => ( 20 |
 21 |           {out}
 22 |         
23 | ))} 24 | {stderr && stderr.length > 0 && stderr.map((err: string, index: number) => ( 25 |
 26 |           {err}
 27 |         
28 | ))} 29 |
30 | ) 31 | } 32 | 33 | 34 | 35 | export interface CodeExecResult { 36 | stdout: string[] 37 | stderr: string[] 38 | runtimeError?: ExecutionError 39 | cellResults: Result[] 40 | } 41 | 42 | export function ArtifactView({ 43 | result, 44 | }: { 45 | result?: CodeExecResult 46 | }) { 47 | // console.log('ArtifactView.result', result); 48 | if (!result) return null 49 | 50 | const { cellResults, stdout, stderr, runtimeError } = result 51 | // The AI-generated code experienced runtime error 52 | if (runtimeError) { 53 | const { name, value, tracebackRaw } = runtimeError 54 | return ( 55 |
56 | 57 | 58 | {name}: {value} 59 | 60 | {tracebackRaw} 61 | 62 | 63 |
64 | ) 65 | } 66 | 67 | // Cell results can contain text, pdfs, images, and code (html, latex, json) 68 | // TODO: Check other formats than `png` 69 | if (cellResults.length > 0) { 70 | if (cellResults[0].png){ 71 | return ( 72 | <> 73 |
74 | {cellResults.map((result, index) => ( 75 | result 82 | 83 | ))} 84 |
85 | 86 | 87 | ) 88 | }else if (cellResults[0].html){ 89 | // console.log('ArtifactView.cellResults', cellResults); 90 | return( 91 | //
92 |