Applicazione di generazione di immagini senza server utilizzando l’intelligenza artificiale generativa su AWS

Creazione di immagini generative senza server attraverso l'intelligenza artificiale su AWS

Se si tratta di creare contenuti personalizzati o adattare le immagini alle preferenze degli utenti, la capacità di generare risorse visuali basate su una descrizione è molto potente. Ma la conversione da testo a immagine di solito implica l’implementazione di una soluzione di machine learning end-to-end, molto intensiva in termini di risorse. E se questa capacità fosse a portata di chiamata API, rendendo così il processo più semplice e accessibile per gli sviluppatori?

In questo tutorial ti guideremo su come utilizzare AWS CDK per implementare un’applicazione di generazione di immagini Serverless utilizzando AWS Lambda e Amazon Bedrock, un servizio completamente gestito che rende accessibili modelli di base di Amazon e fornitori di modelli di terze parti (come Anthropic, Cohere e altri) tramite un’API. Gli sviluppatori possono sfruttare i modelli di base leader attraverso una singola API, mantenendo la flessibilità di adottare nuovi modelli in futuro.

La soluzione viene distribuita come un sito web statico ospitato su Amazon S3 accessibile tramite un dominio di Amazon CloudFront. Gli utenti possono inserire la descrizione dell’immagine che verrà passata a una funzione Lambda (tramite Amazon API Gateway) che a sua volta invocherà il modello di diffusione stabile su Amazon Bedrock per generare l’immagine.

L’intera soluzione è costruita utilizzando Go: questo include la funzione Lambda (utilizzando la libreria aws-lambda-go di AWS) così come l’implementazione completa della soluzione utilizzando AWS CDK.

Il codice è disponibile su GitHub.

Prerequisiti

Prima di iniziare questo tutorial, avrai bisogno delle seguenti cose:

  • Un account AWS (se non ne hai ancora uno, puoi crearne uno e configurare il tuo ambiente qui)
  • Go (v1.19 o versione successiva)
  • AWS CDK
  • AWS CLI
  • Git
  • Docker

Clona questo repository di GitHub e cambia la directory corretta:

git clone https://github.com/build-on-aws/amazon-bedrock-lambda-image-generation-golangcd amazon-bedrock-lambda-image-generation-golang

Distribuisci la soluzione utilizzando AWS CDK

Per avviare la distribuzione, invoca semplicemente cdk deploy.

cd cdkexport DOCKER_DEFAULT_PLATFORM=linux/amd64cdk deploy

Vedrai una lista di risorse che verranno create e dovrai confermare per procedere (output abbreviato per brevità).

Bundle dell'asset BedrockLambdaImgeGenWebsiteStack/bedrock-imagegen-s3/Code/Stage...✨  Tempo di sintesi: 7.84s//.... omessoQuesta distribuzione apporterà modifiche potenzialmente sensibili in base al tuo livello di approvazione della sicurezza attuale (--require-approval broadening). Conferma di voler apportare le seguenti modifiche://.... omessoVuoi effettuare queste modifiche (s/n)? y

Inizierà quindi la creazione delle risorse AWS necessarie per l’applicazione.

Se vuoi vedere il modello AWS CloudFormation che verrà utilizzato dietro le quinte, esegui il comando cdk synth e controlla la cartella cdk.out.

Puoi seguire il progresso nel terminale o accedere alla console AWS: CloudFormation > Stacks > BedrockLambdaImgeGenWebsiteStack.

Una volta create tutte le risorse, puoi provare l’applicazione. Dovresti avere:

  • La funzione Lambda di generazione dell’immagine e l’API Gateway
  • Un bucket S3 per ospitare la pagina HTML del sito web
  • Distribuzione di CloudFront
  • E alcuni altri componenti (come ruoli IAM, autorizzazioni, policy del bucket S3, ecc.)

L’implementazione può richiedere un po’ di tempo poiché la creazione della distribuzione di CloudFront è un processo che richiede tempo. Una volta completato, dovresti ricevere una conferma insieme ai valori del nome del bucket S3, dell’URL di API Gateway e del nome di dominio di CloudFront.

Aggiorna la Pagina HTML e Copiala nel Bucket S3

Apri il file index.html nel repository GitHub e individua il seguente testo: ENTER_API_GATEWAY_URL. Sostituiscilo con l’URL di API Gateway che hai ricevuto come output dell’implementazione CDK sopra.

Per copiare il file in S3, ho usato l’AWS CLI:

aws s3 cp index.html s3://<nome del bucket S3 dall'output di CDK>

Verifica che il file sia stato caricato:

aws s3 ls s3://<nome del bucket S3 dall'output di CDK>

Ora sei pronto per accedere al sito web!

Verifica la Soluzione

Inserisci il nome di dominio di CloudFront nel tuo browser web per navigare al sito web. Dovresti vedere il sito web con una descrizione precompilata che può essere utilizzata come prompt.

Fai clic su Genera Immagine per avviare il processo. Dopo alcuni secondi, dovresti vedere l’immagine generata.

Modifica i Parametri del Modello

Il modello Stability Diffusion ci consente di raffinare i parametri di generazione secondo le nostre esigenze.

I modelli Stability.ai Diffusion supportano i seguenti controlli:

  • Forza del Prompt (cfg_scale) controlla la fedeltà dell’immagine al prompt, con valori più bassi che aumentano la casualità.
  • Passo di Generazione (steps) determina l’accuratezza del risultato, con più passi che producono immagini più precise.
  • Seed (seed) imposta il livello di rumore iniziale, consentendo risultati riproducibili quando si utilizza lo stesso seed e le stesse impostazioni.

Fai clic su Mostra Configurazione per modificarli.

I valori massimi per cfg_steps e steps sono rispettivamente 30 e 150.

Non Dimenticare di Fare Pulizia

Una volta finito, per eliminare tutti i servizi, usa semplicemente:

cdk destroy#output prompt (choose 'y' to continue)Are you sure you want to delete: BedrockLambdaImgeGenWebsiteStack (y/n)?

Hai potuto configurare e provare la soluzione completa. Prima di concludere, facciamo una rapida panoramica delle parti importanti del codice per capire meglio cosa accade dietro le quinte.

Analisi del Codice

Dato che ci concentreremo solo sugli elementi importanti, gran parte del codice (istruzioni di stampa, gestione degli errori, ecc.) è stato omesso per brevità.

CDK

Puoi fare riferimento al codice CDK qui.

Iniziamo creando l’API Gateway e il bucket S3.

    apigw := awscdkapigatewayv2alpha.NewHttpApi(stack, jsii.String("image-gen-http-api"), nil)    bucket := awss3.NewBucket(stack, jsii.String("website-s3-bucket"), &awss3.BucketProps{        BlockPublicAccess: awss3.BlockPublicAccess_BLOCK_ALL(),        RemovalPolicy:     awscdk.RemovalPolicy_DESTROY,        AutoDeleteObjects: jsii.Bool(true),    })

Poi creiamo l’Identity di Accesso all’Origine di CloudFront e concediamo autorizzazioni di lettura del bucket S3 all’identità di accesso all’origine di CloudFront:

    oai := awscloudfront.NewOriginAccessIdentity(stack, jsii.String("OAI"), nil)    bucket.GrantRead(oai.GrantPrincipal(), "*")    distribution := awscloudfront.NewDistribution(stack, jsii.String("MyDistribution"), &awscloudfront.DistributionProps{        DefaultBehavior: &awscloudfront.BehaviorOptions{            Origin: awscloudfrontorigins.NewS3Origin(bucket, &awscloudfrontorigins.S3OriginProps{                OriginAccessIdentity: oai,            }),        },        DefaultRootObject: jsii.String("index.html"), //nome del file in S3    })

Successivamente, creiamo la funzione Lambda per la generazione delle immagini insieme alle autorizzazioni IAM (per il ruolo IAM dell’esecuzione della funzione) per consentirgli di richiamare le operazioni di Bedrock.

    function := awscdklambdagoalpha.NewGoFunction(stack, jsii.String("bedrock-imagegen-s3"),        &awscdklambdagoalpha.GoFunctionProps{            Runtime: awslambda.Runtime_GO_1_X(),            Entry:   jsii.String(functionDir),            Timeout: awscdk.Duration_Seconds(jsii.Number(30)),        })    function.AddToRolePolicy(awsiam.NewPolicyStatement(&awsiam.PolicyStatementProps{        Actions:   jsii.Strings("bedrock:*"),        Effect:    awsiam.Effect_ALLOW,        Resources: jsii.Strings("*"),    }))

Infine, configuriamo l’integrazione della funzione Lambda con API Gateway, aggiungiamo le route HTTP e specifichiamo l’endpoint di API Gateway, il nome del bucket S3 e il nome di dominio di CloudFront come output di CloudFormation.

    functionIntg := awscdkapigatewayv2integrationsalpha.NewHttpLambdaIntegration(jsii.String("function-integration"), function, nil)    apigw.AddRoutes(&awscdkapigatewayv2alpha.AddRoutesOptions{        Path:        jsii.String("/"),        Methods:     &[]awscdkapigatewayv2alpha.HttpMethod{awscdkapigatewayv2alpha.HttpMethod_POST},        Integration: functionIntg})    awscdk.NewCfnOutput(stack, jsii.String("apigw URL"), &awscdk.CfnOutputProps{Value: apigw.Url(), Description: jsii.String("Endpoint di API Gateway")})    awscdk.NewCfnOutput(stack, jsii.String("nome dominio CloudFront"), &awscdk.CfnOutputProps{Value: distribution.DomainName(), Description: jsii.String("Nome dominio CloudFront")})    awscdk.NewCfnOutput(stack, jsii.String("nome bucket S3"), &awscdk.CfnOutputProps{Value: bucket.BucketName(), Description: jsii.String("Nome bucket S3")})

Funzione Lambda

Puoi fare riferimento al codice della funzione Lambda qui.

Nel gestore della funzione, estraiamo il prompt dal corpo della richiesta HTTP e la configurazione dai parametri di query. Quindi viene utilizzato per chiamare il modello usando la funzione bedrockruntime.InvokeModel. Nota che il payload JSON inviato ad Amazon Bedrock è rappresentato da un’istanza della struttura Request.

Il corpo di output restituito dal modello di diffusione stabile di Amazon Bedrock è un payload JSON che viene convertito in una struttura Response che contiene l’immagine generata come stringa base64. Questo viene restituito come oggetto events.APIGatewayV2HTTPResponse insieme agli header CORS.

func handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) {    prompt := req.Body    cfgScaleF, _ := strconv.ParseFloat(req.QueryStringParameters["cfg_scale"], 64)    seed, _ := strconv.Atoi(req.QueryStringParameters["seed"])    steps, _ := strconv.Atoi(req.QueryStringParameters["steps"])    payload := Request{        TextPrompts: []TextPrompt{{Text: prompt}},        CfgScale:    cfgScaleF,        Steps: steps,    }    if seed > 0 {        payload.Seed = seed    }    payloadBytes, err := json.Marshal(payload)    output, err := brc.InvokeModel(context.Background(), &bedrockruntime.InvokeModelInput{        Body:        payloadBytes,        ModelId:     aws.String(stableDiffusionXLModelID),        ContentType: aws.String("application/json"),    })    var resp Response    err = json.Unmarshal(output.Body, &resp)    image := resp.Artifacts[0].Base64    return events.APIGatewayV2HTTPResponse{        StatusCode:      http.StatusOK,        Body:            image,        IsBase64Encoded: false,        Headers: map[string]string{            "Access-Control-Allow-Origin":  "*",            "Access-Control-Allow-Methods": "POST,OPTIONS",        },    }, nil}//modello richiesta/rispostatype Request struct {    TextPrompts []TextPrompt `json:"text_prompts"`    CfgScale    float64      `json:"cfg_scale"`    Steps       int          `json:"steps"`    Seed        int          `json:"seed"`}type TextPrompt struct {    Text string `json:"text"`}type Response struct {    Result    string     `json:"result"`    Artifacts []Artifact `json:"artifacts"`}type Artifact struct {    Base64       string `json:"base64"`    FinishReason string `json:"finishReason"`}

Conclusion

In questo tutorial, hai utilizzato AWS CDK per distribuire una soluzione di generazione di immagini serverless implementata utilizzando Amazon Bedrock e AWS Lambda e accessibile tramite un sito web statico su S3 tramite un dominio CloudFront.

Se sei interessato a una guida introduttiva sull’utilizzo dell’AWS Go SDK e dei modelli fondamentali di Amazon Bedrock (FMs), consulta questo articolo nel blog.

Divertiti a creare!