Implementare un endpoint di inferenza ML serverless per grandi modelli di linguaggio utilizzando FastAPI, AWS Lambda e AWS CDK.

Implement a serverless ML inference endpoint for large language models using FastAPI, AWS Lambda and AWS CDK.

Per i data scientist, spostare i modelli di machine learning (ML) dalla prova di concetto alla produzione rappresenta spesso una sfida significativa. Uno dei principali ostacoli può essere il deploy di un modello ben performante, addestrato localmente, nel cloud per l’elaborazione e l’uso in altre applicazioni. Può essere complicato gestire il processo, ma con lo strumento giusto, è possibile ridurre significativamente lo sforzo richiesto.

L’elaborazione inferenziale di Amazon SageMaker, resa disponibile a livello generale nell’aprile del 2022, rende facile per te il deploy dei modelli di ML in produzione per effettuare previsioni su larga scala, fornendo una vasta selezione di infrastrutture di ML e opzioni di deploy di modelli per aiutare a soddisfare tutti i tipi di esigenze inferenziali di ML. Puoi utilizzare i punti di ingresso del serverless di SageMaker per carichi di lavoro che presentano periodi di inattività tra gli impulsi di traffico e possono tollerare i cold start. I punti di ingresso si ridimensionano automaticamente in base al traffico e rimuovono il carico di lavoro pesante non differenziato della selezione e della gestione dei server. Inoltre, puoi utilizzare AWS Lambda direttamente per esporre i tuoi modelli e deployare le tue applicazioni di ML utilizzando il tuo framework open source preferito, il che può dimostrarsi più flessibile ed economico.

FastAPI è un moderno framework web ad alte prestazioni per la costruzione di API con Python. Si distingue quando si tratta di sviluppare applicazioni serverless con microservizi RESTful e casi d’uso che richiedono un’elaborazione inferenziale di ML su larga scala in molteplici settori. La sua facilità e le funzionalità integrate come la documentazione API automatica lo rendono una scelta popolare tra gli ingegneri di ML per il deploy di API di elaborazione ad alte prestazioni. Puoi definire e organizzare le tue route utilizzando funzionalità out-of-the-box di FastAPI per ridimensionare e gestire la logica aziendale in crescita come necessario, testare localmente e ospitarlo su Lambda, quindi esporlo attraverso un unico gateway API, che ti consente di portare un framework web open source su Lambda senza alcun lavoro pesante o riconfigurazione del tuo codice.

Questo post ti mostra come effettuare facilmente l’elaborazione inferenziale di ML serverless esponendo il tuo modello di ML come endpoint utilizzando FastAPI, Docker, Lambda e Amazon API Gateway. Ti mostriamo anche come automatizzare il deploy utilizzando il kit di sviluppo cloud di AWS (AWS CDK).

Panoramica della soluzione

Il diagramma seguente mostra l’architettura della soluzione che deployiamo in questo post.

Prerequisiti

Devi avere i seguenti prerequisiti:

  • Python3 installato, insieme a virtualenv per la creazione e la gestione di ambienti virtuali in Python
  • aws-cdk v2 installato sul tuo sistema per poter utilizzare la CLI di AWS CDK
  • Docker installato e in esecuzione sulla tua macchina locale

Verifica se tutti i software necessari sono installati:

  1. È necessaria l’interfaccia della riga di comando di Amazon Web Services (AWS CLI). Accedi al tuo account e scegli la regione in cui desideri deployare la soluzione.

  2. Utilizza il seguente codice per verificare la versione di Python:

    python3 --version
  3. Verifica se virtualenv è installato per la creazione e la gestione di ambienti virtuali in Python. In senso stretto, questo non è un requisito indispensabile, ma renderà la vita più facile e aiuterà a seguire questo post più facilmente. Utilizza il seguente codice:

    python3 -m virtualenv --version
  4. Verifica se cdk è installato. Questo verrà utilizzato per deployare la nostra soluzione.

    cdk --version
  5. Verifica se Docker è installato. La nostra soluzione renderà il tuo modello accessibile tramite un’immagine Docker a Lambda. Per creare questa immagine localmente, abbiamo bisogno di Docker.

    docker --version
  6. Assicurati che Docker sia attivo ed in esecuzione con il seguente codice:

    docker ps

Come strutturare il tuo progetto FastAPI utilizzando AWS CDK

Utilizziamo la seguente struttura di directory per il nostro progetto (ignorando un po’ di codice boilerplate di AWS CDK che non è importante nel contesto di questo post):

```

fastapi_model_serving
│
└───.venv
│
└───fastapi_model_serving
│   │   __init__.py
│   │   fastapi_model_serving_stack.py
│   │
│   └───model_endpoint
│       └───docker
│       │      Dockerfile
│       │      serving_api.tar.gz
│
│
│       └───runtime
│            └───serving_api
│                    requirements.txt
│                    serving_api.py
│                └───custom_lambda_utils
│                     └───model_artifacts
│                            ...
│                     └───scripts
│                            inference.py
│
└───templates
│   └───api
│   │     api.py
│   └───dummy
│         dummy.py
│
│ app.py
│   cdk.json
│   README.md
│   requirements.txt
│   init-lambda-code.sh

```

La directory segue la struttura raccomandata dei progetti AWS CDK per Python.

La parte più importante di questo repository è la directory fastapi_model_serving. Contiene il codice che definirà lo stack AWS CDK e le risorse che verranno utilizzate per il model serving.

La directory fastapi_model_serving contiene la sottodirectory model_endpoint, che contiene tutti gli asset necessari per creare il nostro endpoint senza server nel Cloud, ovvero il Dockerfile per creare l’immagine Docker che Lambda utilizzerà, il codice della funzione Lambda che utilizza FastAPI per gestire le richieste di inferenza e inviarle all’endpoint corretto, e gli artefatti del modello che vogliamo distribuire. model_endpoint contiene anche quanto segue:

  • Docker – Questa sottodirectory contiene quanto segue:
  • Dockerfile – Questo viene utilizzato per creare l’immagine per la funzione Lambda con tutti gli artefatti (codice della funzione Lambda, artefatti del modello, ecc.) nel posto giusto in modo che possano essere utilizzati senza problemi.
  • serving.api.tar.gz – Questo è un tarball che contiene tutti gli asset dalla cartella runtime che sono necessari per creare l’immagine Docker. Discuteremo come creare il file .tar.gz più tardi in questo post.
  • runtime – Questa sottodirectory contiene quanto segue:
  • serving_api – Il codice della funzione Lambda e le relative dipendenze specificate nel file requirements.txt.
  • custom_lambda_utils – Questo include uno script di inferenza che carica gli artefatti del modello necessari in modo che il modello possa essere passato alla serving_api che lo esporrà come endpoint.

Inoltre, abbiamo la directory template, che fornisce un modello di strutture di cartelle e file in cui è possibile definire i propri codici personalizzati e API seguendo l’esempio che abbiamo visto in precedenza. La directory template contiene del codice fittizio che è possibile utilizzare per creare nuove funzioni Lambda:

  • dummy – Contiene il codice che implementa la struttura di una funzione Lambda ordinaria utilizzando l’ambiente di runtime Python
  • api – Contiene il codice che implementa una funzione Lambda che avvolge un endpoint FastAPI attorno a una gateway API esistente

Deploy della soluzione

Per impostazione predefinita, il codice viene distribuito nella regione eu-west-1. Se si desidera modificare la regione, è possibile modificare la variabile di contesto DEPLOYMENT_REGION nel file cdk.json.

Tuttavia, tenete presente che la soluzione cerca di distribuire una funzione Lambda in cima all’architettura arm64, e questa funzionalità potrebbe non essere disponibile in tutte le regioni. In questo caso, è necessario modificare il parametro di architettura nel file fastapi_model_serving_stack.py, nonché la prima riga del Dockerfile all’interno della directory Docker, per ospitare questa soluzione sull’architettura x86.

Per distribuire la soluzione, completare i seguenti passaggi:

  1. Eseguire il seguente comando per clonare il repository GitHub: git clone https://github.com/aws-samples/lambda-serverless-inference-fastapi Poiché vogliamo mostrare che la soluzione può funzionare con artefatti del modello che si addestrano localmente, contengono un artefatto del modello di esempio di un modello DistilBERT preaddestrato sul Hugging Face model hub per un’attività di risposta alle domande nel file serving_api.tar.gz. Il tempo di download può richiedere circa 3-5 minuti. Ora, procediamo con la configurazione dell’ambiente.

  2. Scaricare il modello preaddestrato che verrà distribuito dal Hugging Face model hub nella directory ./model_endpoint/runtime/serving_api/custom_lambda_utils/model_artifacts. Crea anche un ambiente virtuale e installa tutte le dipendenze necessarie. È sufficiente eseguire questo comando una volta: make prep. Questo comando può richiedere circa 5 minuti (a seconda della larghezza di banda di Internet) poiché deve scaricare gli artefatti del modello.

  3. Imballare gli artefatti del modello all’interno di un archivio .tar.gz che verrà utilizzato all’interno dell’immagine Docker che verrà creata nello stack AWS CDK. È necessario eseguire questo codice ogni volta che si apportano modifiche agli artefatti del modello o all’API stessa per avere sempre la versione più aggiornata del proprio endpoint di servizio: make package_model. Gli artefatti sono tutti al loro posto. Ora possiamo distribuire lo stack AWS CDK nel proprio account AWS.

  4. Eseguire cdk bootstrap se è la prima volta che si distribuisce un’app AWS CDK in un ambiente (combinazione account + regione):

    make cdk_bootstrap

    Questo stack include le risorse necessarie per l’operazione del toolkit. Ad esempio, lo stack include un bucket Amazon Simple Storage Service (Amazon S3) che viene utilizzato per archiviare modelli e asset durante il processo di distribuzione.

    Poiché stiamo creando immagini Docker localmente in questa distribuzione AWS CDK, è necessario assicurarsi che il daemon Docker sia in esecuzione prima di poter distribuire questo stack tramite la CLI AWS CDK.

  5. Per verificare se il daemon Docker è in esecuzione nel proprio sistema, utilizzare il seguente comando:

    docker ps

    Se non si riceve un messaggio di errore, si è pronti per distribuire la soluzione.

  6. Distribuire la soluzione con il seguente comando:

    make deploy

    Questa operazione può richiedere circa 5-10 minuti a causa della creazione e dell’invio dell’immagine Docker.

Risoluzione dei problemi

Se sei un utente Mac, potresti incontrare un errore durante l’accesso ad Amazon Elastic Container Registry (Amazon ECR) con il login Docker, come ad esempio Errore nel salvataggio delle credenziali ... non implementato. Ad esempio:

uscito con il codice di errore 1: Errore nel salvataggio delle credenziali: errore durante la memorizzazione delle credenziali - err: stato di uscita 1,...dial unix backend.sock: connect: connection refused

Prima di poter utilizzare Lambda su container Docker all’interno di AWS CDK, potresti dover modificare il file ~/docker/config.json. In particolare, potresti dover modificare il parametro credsStore in ~/.docker/config.json in osxkeychain. Questo risolve i problemi di accesso a Amazon ECR su un Mac.

Eseguire l’elaborazione in tempo reale

Dopo che lo stack di AWS CloudFormation è stato implementato con successo, vai alla scheda Outputs per il tuo stack nella console di AWS CloudFormation e apri l’URL del punto di accesso. Ora il nostro modello è accessibile tramite l’URL del punto di accesso e siamo pronti per l’esecuzione dell’elaborazione in tempo reale.

Naviga all’URL per vedere se riesci a visualizzare il messaggio “hello world” e aggiungi /docs all’indirizzo per vedere se riesci a visualizzare con successo la pagina swagger UI interattiva. Potrebbe esserci un po’ di tempo di avvio a freddo, quindi potresti dover attendere o aggiornare alcune volte.

Dopo aver effettuato l’accesso alla pagina di destinazione della pagina swagger UI di FastAPI, puoi eseguire l’elaborazione tramite la radice / o tramite /question.

Dalla radice /, puoi eseguire l’API e ottenere il messaggio “hello world”.

Da /question, puoi eseguire l’API ed eseguire l’elaborazione ML sul modello che abbiamo implementato per un caso di risposta alle domande. Ad esempio, usiamo la domanda “Qual è il colore della mia macchina adesso?” e il contesto è “La mia macchina era blu ma l’ho dipinta di rosso”.

Quando scegli Esegui, in base al contesto fornito, il modello risponderà alla domanda con una risposta, come mostrato nella seguente schermata.

Nel corpo della risposta, puoi vedere la risposta con il punteggio di confidenza del modello. Puoi anche sperimentare con altri esempi o incorporare l’API nella tua applicazione esistente.

In alternativa, puoi eseguire l’elaborazione tramite codice. Ecco un esempio scritto in Python, utilizzando la libreria requests:

import requests

url = "https://<YOUR_API_GATEWAY_ENDPOINT_ID>.execute-api.<YOUR_ENDPOINT_REGION>.amazonaws.com/prod/question?question=\"What is the color of my car now?\"&context=\"My car used to be blue but I painted red\""

response = requests.request("GET", url, headers=headers, data=payload)

print(response.text)

Il codice restituisce una stringa simile alla seguente:

'{"score":0.6947233080863953,"start":38,"end":41,"answer":"red"}'

Se sei interessato a conoscere di più sulla distribuzione di Generative AI e grandi modelli di linguaggio su AWS, guarda qui:

  • Implementa Generative AI serverless su AWS Lambda con OpenLLaMa
  • Implementa grandi modelli di linguaggio su AWS Inferentia2 utilizzando i container di elaborazione di grandi modelli

Pulizia

All’interno della directory principale del tuo repository, esegui il seguente codice per eliminare le tue risorse:

make destroy

Conclusione

In questo articolo, abbiamo introdotto come è possibile utilizzare Lambda per distribuire il proprio modello di apprendimento automatico addestrato utilizzando il proprio framework di applicazione web preferito, come ad esempio FastAPI. Abbiamo fornito un repository di codice dettagliato che è possibile distribuire, e si mantiene la flessibilità di passare a qualsiasi artefatto di modello addestrato che si elabora. Le prestazioni possono dipendere da come si implementa e distribuisce il modello.

Siete invitati a provarlo voi stessi, e siamo entusiasti di sentire i vostri commenti!