From 1a571a236878e4e32f55056e5693db38837d3c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thor=20=E9=9B=B7=E7=A5=9E=20Schaeff?= <5748289+thorwebdev@users.noreply.github.com> Date: Sat, 1 Jun 2024 22:28:39 +0800 Subject: [PATCH] docs: edgy bedrock. (#26909) * docs: edgy bedrock. * fix: nav. * Apply suggestions from code review Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> --------- Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> --- .../NavigationMenu.constants.ts | 4 + apps/docs/content/guides/functions.mdx | 5 + .../amazon-bedrock-image-generator.mdx | 150 ++++++++++++++++++ .../examples/cloudflare-turnstile.mdx | 11 +- .../supabase/.env.example | 8 + 5 files changed, 168 insertions(+), 10 deletions(-) create mode 100644 apps/docs/content/guides/functions/examples/amazon-bedrock-image-generator.mdx create mode 100644 examples/ai/aws_bedrock_image_gen/supabase/.env.example diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 8146b7d252c..66701ebbed8 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -1189,6 +1189,10 @@ export const functions: NavMenuConstant = { name: 'Sending Push Notifications', url: '/guides/functions/examples/push-notifications', }, + { + name: 'Generating AI images', + url: '/guides/functions/examples/amazon-bedrock-image-generator', + }, { name: 'Generating OG images ', url: '/guides/functions/examples/og-image', diff --git a/apps/docs/content/guides/functions.mdx b/apps/docs/content/guides/functions.mdx index a326898f1b5..960cfc34f19 100644 --- a/apps/docs/content/guides/functions.mdx +++ b/apps/docs/content/guides/functions.mdx @@ -108,6 +108,11 @@ Check out the [Edge Function Examples](https://github.com/supabase/supabase/tree description: `Access 100,000+ Machine Learning models.`, href: '/guides/ai/examples/huggingface-image-captioning', }, + { + name: 'Amazon Bedrock', + description: `Amazon Bedrock Image Generator`, + href: '/guides/functions/examples/amazon-bedrock-image-generator', + }, { name: 'OpenAI', description: `Using OpenAI in Edge Functions.`, diff --git a/apps/docs/content/guides/functions/examples/amazon-bedrock-image-generator.mdx b/apps/docs/content/guides/functions/examples/amazon-bedrock-image-generator.mdx new file mode 100644 index 00000000000..7b3c2b10730 --- /dev/null +++ b/apps/docs/content/guides/functions/examples/amazon-bedrock-image-generator.mdx @@ -0,0 +1,150 @@ +--- +id: 'examples-amazon-bedrock-image-generator' +title: 'Generate Images with Amazon Bedrock' +description: 'Generate images with Amazon Bedrock and store them in Supabase Storage.' +tocVideo: 'KIwN2TmkTlg' +--- + +[Amazon Bedrock](https://aws.amazon.com/bedrock) is a fully managed service that offers a choice of high-performing foundation models (FMs) from leading AI companies like AI21 Labs, Anthropic, Cohere, Meta, Mistral AI, Stability AI, and Amazon. Each model is accessible through a common API which implements a broad set of features to help build generative AI applications with security, privacy, and responsible AI in mind. + +This guide will walk you through an example using the Amazon Bedrock JavaScript SDK in Supabase Edge Functions to generate images using the [Amazon Titan Image Generator G1](https://aws.amazon.com/blogs/machine-learning/use-amazon-titan-models-for-image-generation-editing-and-searching/) model. + +## Setup + +- In your AWS console, navigate to Amazon Bedrock and under "Request model access", select the Amazon Titan Image Generator G1 model. +- In your Supabase project, create a `.env` file in the `supabase` directory with the following contents: + +```txt +AWS_DEFAULT_REGION="" +AWS_ACCESS_KEY_ID="" +AWS_SECRET_ACCESS_KEY="" +AWS_SESSION_TOKEN="" + +# Mocked config files +AWS_SHARED_CREDENTIALS_FILE="./aws/credentials" +AWS_CONFIG_FILE="./aws/config" +``` + +### Configure Storage + +- [locally] Run `supabase start` +- Open Studio URL: [locally](http://127.0.0.1:54323/project/default/storage/buckets) | [hosted](https://app.supabase.com/project/_/storage/buckets) +- Navigate to Storage +- Click "New bucket" +- Create a new public bucket called "images" + +## Code + +Create a new function in your project: + +```bash +supabase functions new amazon-bedrock +``` + +And add the code to the `index.ts` file: + +```ts index.ts +// We need to mock the file system for the AWS SDK to work. +import { prepareVirtualFile } from 'https://deno.land/x/mock_file@v1.1.2/mod.ts' + +import { BedrockRuntimeClient, InvokeModelCommand } from 'npm:@aws-sdk/client-bedrock-runtime' +import { createClient } from 'npm:@supabase/supabase-js' +import { decode } from 'npm:base64-arraybuffer' + +console.log('Hello from Amazon Bedrock!') + +Deno.serve(async (req) => { + prepareVirtualFile('./aws/config') + prepareVirtualFile('./aws/credentials') + + const client = new BedrockRuntimeClient({ + region: Deno.env.get('AWS_DEFAULT_REGION') ?? 'us-west-2', + credentials: { + accessKeyId: Deno.env.get('AWS_ACCESS_KEY_ID') ?? '', + secretAccessKey: Deno.env.get('AWS_SECRET_ACCESS_KEY') ?? '', + sessionToken: Deno.env.get('AWS_SESSION_TOKEN') ?? '', + }, + }) + + const { prompt, seed } = await req.json() + console.log(prompt) + const input = { + contentType: 'application/json', + accept: '*/*', + modelId: 'amazon.titan-image-generator-v1', + body: JSON.stringify({ + taskType: 'TEXT_IMAGE', + textToImageParams: { text: prompt }, + imageGenerationConfig: { + numberOfImages: 1, + quality: 'standard', + cfgScale: 8.0, + height: 512, + width: 512, + seed: seed ?? 0, + }, + }), + } + + const command = new InvokeModelCommand(input) + const response = await client.send(command) + console.log(response) + + if (response.$metadata.httpStatusCode === 200) { + const { body, $metadata } = response + + const textDecoder = new TextDecoder('utf-8') + const jsonString = textDecoder.decode(body.buffer) + const parsedData = JSON.parse(jsonString) + console.log(parsedData) + const image = parsedData.images[0] + + const supabaseClient = createClient( + // Supabase API URL - env var exported by default. + Deno.env.get('SUPABASE_URL')!, + // Supabase API ANON KEY - env var exported by default. + Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')! + ) + + const { data: upload, error: uploadError } = await supabaseClient.storage + .from('images') + .upload(`${$metadata.requestId ?? ''}.png`, decode(image), { + contentType: 'image/png', + cacheControl: '3600', + upsert: false, + }) + if (!upload) { + return Response.json(uploadError) + } + const { data } = supabaseClient.storage.from('images').getPublicUrl(upload.path!) + return Response.json(data) + } + + return Response.json(response) +}) +``` + +## Run the function locally + +1. Run `supabase start` (see: https://supabase.com/docs/reference/cli/supabase-start) +2. Start with env: `supabase functions serve --env-file supabase/.env` +3. Make an HTTP request: + +```bash + curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/amazon-bedrock' \ + --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \ + --header 'Content-Type: application/json' \ + --data '{"prompt":"A beautiful picture of a bird"}' +``` + +4. Navigate back to your storage bucket. You might have to hit the refresh button to see the uploaded image. + +## Deploy to your hosted project + +```bash +supabase link +supabase functions deploy amazon-bedrock +supabase secrets set --env-file supabase/.env +``` + +That's it, you've now deployed a serverless function that uses AI to generate and upload images to your Supabase storage bucket. diff --git a/apps/docs/content/guides/functions/examples/cloudflare-turnstile.mdx b/apps/docs/content/guides/functions/examples/cloudflare-turnstile.mdx index 702f4871bcf..58072cb3306 100644 --- a/apps/docs/content/guides/functions/examples/cloudflare-turnstile.mdx +++ b/apps/docs/content/guides/functions/examples/cloudflare-turnstile.mdx @@ -2,18 +2,9 @@ id: 'examples-cloudflare-turnstile' title: 'CAPTCHA support with Cloudflare Turnstile' description: 'Protecting Forms with Cloudflare Turnstile.' -video: 'https://www.youtube.com/v/OwW0znboh60' +tocVideo: 'OwW0znboh60' --- -
- -
- [Cloudflare Turnstile](https://www.cloudflare.com/products/turnstile/) is a friendly, free CAPTCHA replacement, and it works seamlessly with Supabase Edge Functions to protect your forms. [View on GitHub](https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/cloudflare-turnstile). ## Setup diff --git a/examples/ai/aws_bedrock_image_gen/supabase/.env.example b/examples/ai/aws_bedrock_image_gen/supabase/.env.example new file mode 100644 index 00000000000..72e86a899ab --- /dev/null +++ b/examples/ai/aws_bedrock_image_gen/supabase/.env.example @@ -0,0 +1,8 @@ +AWS_DEFAULT_REGION="us-west-2" +AWS_ACCESS_KEY_ID="" +AWS_SECRET_ACCESS_KEY="" +AWS_SESSION_TOKEN="" + +# Mocked config files +AWS_SHARED_CREDENTIALS_FILE="./aws/credentials" +AWS_CONFIG_FILE="./aws/config" \ No newline at end of file