Vai al contenuto principale

Come distribuire applicazioni LLM con Docker: guida passo passo

Questo tutorial ti insegna a usare Docker per creare e distribuire un'applicazione di Q&A su documenti su Hugging Face Cloud.
Aggiornato 29 set 2026  · 10 min leggi

Scopri con l'IA

ChatGPTClaudePerplexity

Docker ti permette di creare ambienti coerenti, portabili e isolati, rendendolo essenziale per le LLMOps (Large Language Models Operations). Incapsulando diverse applicazioni LLM e le loro dipendenze in container, Docker semplifica la distribuzione, assicura la compatibilità tra sistemi e snellisce i test.

In questo tutorial imparerai a creare un'applicazione chatbot di “domande e risposte su documenti” e a distribuirla sul cloud usando Docker. Useremo Gradio per l'interfaccia utente, LlamaIndex per l'orchestrazione, LlamaParse per il parsing dei documenti, Mixedbread AI per gli embedding, Groq per accedere ai modelli linguistici di grandi dimensioni, Docker per impacchettare l'applicazione e le sue dipendenze, e Hugging Face Spaces per distribuire l'app sul cloud.

Questo tutorial è pensato per essere semplice, così chiunque, anche con conoscenze limitate su come funzionano le applicazioni di AI, può costruirlo gratuitamente.

Descrizione del progetto

Ci sono due approcci principali per sviluppare e distribuire applicazioni di AI:

  • Completamente open source: Questo approccio enfatizza privacy e protezione dei dati.
  • Completamente closed source: Questo metodo prevede l'integrazione di più API e servizi cloud.

Entrambi gli approcci hanno pro e contro. Nel nostro caso, abbiamo scelto il secondo, integrando più servizi di AI. Questo ci permette di costruire un'app veloce che richiede solo pochi secondi per essere creata e distribuita. Il nostro obiettivo principale è ridurre la dimensione dell'immagine Docker, cosa che può essere ottenuta efficacemente integrando più servizi di AI.

Dai un'occhiata al tutorial Local AI con Docker, n8n, Qdrant e Ollama per costruire un'app LLM usando strumenti e framework open source per una privacy maggiore!

Costruiremo un chatbot di Q&A generico che consente agli utenti di caricare documenti e chattarci in tempo reale. È piuttosto simile al NotebookLM di Google.

Diagramma dell'applicazione Doc Q&A LLM

Diagramma del progetto. Immagine dell'autore

Ecco gli strumenti che useremo in questo progetto:

  1. Gradio Blocks: Per creare un'interfaccia utente che consente di caricare qualsiasi documento di testo e chattare facilmente con il documento.
  2. LlamaCloud: Serve per eseguire il parsing dei file ed estrarre i dati testuali in stile markdown.
  3. MixedBread AI: Viene utilizzato per convertire i documenti caricati e i messaggi in embedding per il recupero del contesto.
  4. Groq Cloud: Serve per ottenere risposte LLM veloci. In questo progetto useremo il modello llama-3.1-70b.
  5. LlamaIndex: Per creare la pipeline RAG (Retrieval Augmented Generation) che orchestra tutti i servizi di AI. La pipeline userà il file caricato e i messaggi dell'utente per generare risposte contestuali.
  6. Docker: Viene utilizzato per incapsulare app, dipendenze, ambiente e configurazioni.
  7. Hugging Face Cloud: Spingeremo tutti i file nel repository Spaces e Hugging Face costruirà automaticamente l'immagine usando il Dockerfile e la distribuirà sul server.

Se sei alle prime armi con gli LLM, valuta il corso Padroneggia i concetti dei Large Language Models (LLM) per imparare terminologia di base, metodologie, considerazioni etiche e le ricerche più recenti.

Prima di costruire l'app LLM, dobbiamo scaricare e installare Docker dal sito ufficiale. 

  • Installa Docker sul tuo sistema locale usando le opzioni predefinite.
  • Poi crea una directory di progetto con il tuo IDE preferito e aggiungi un file .env. Useremo questo file per memorizzare le chiavi API di LlamaCloud, MixedBread AI e Groq Cloud.
  • Dopodiché, registrati su LlamaCloud e genera la tua chiave API. Useremo LlamaCloud per eseguire il parsing di vari formati di testo, inclusi Excel, txt, Word e PDF.

Dashboard LlamaCloud

Generazione di una nuova chiave in LlamaCloud. Fonte immagine: LlamaCloud

  • Poi registrati su MixedBread AI e genera la tua chiave API. Useremo questa chiave per accedere gratuitamente al loro modello di embedding di punta.

Dashboard MixedBread AI

Creazione di una chiave API in MixedBread. Fonte immagine: MixedBread

  • Vai su GroqCloud e registrati per generare gratuitamente la tua chiave API. Useremo GroqCloud per accedere a LLM ad alta velocità.

Dashboard Groq Cloud

Creazione di una chiave API in GroqCloud.  Fonte immagine: GroqCloud

Scopri tutto su GroqCloud leggendo l'articolo sul motore di inferenza Groq LPU. Imparerai le API Groq e le loro funzionalità con esempi di codice. Inoltre, scoprirai come creare applicazioni di AI contestuali usando Groq API e LlamaIndex.

Ecco come dovrebbe apparire il tuo file .env:

LLAMA_CLOUD_API_KEY=llx-XXXXXX
GROQ_API_KEY=gsk_XXXXXXX
MXBAI_API_KEY=emb_XXXXXX

Ricordati di aggiungere il file .env al tuo .gitignore per evitare di esporre accidentalmente le chiavi API al pubblico.

Ora creeremo uno script Python chiamato app.py e aggiungeremo i componenti dell'interfaccia utente integrando tutti i servizi di AI tramite LlamaParser per sviluppare la pipeline Retrieval-Augmented Generation (RAG) con LlamaIndex.

Lo script app.py farà quanto segue:

  1. Caricare tutti i pacchetti Python necessari.
  2. Caricare in modo sicuro tutte le chiavi API dal file .env.
  3. Inizializzare LlamaParser usando la chiave API di LlamaCloud.
  4. Definire un estrattore di file che gestisca varie estensioni comuni.
  5. Inizializzare il modello di embedding usando la chiave API di MixedBread AI, nello specifico il modello mixedbread-ai/mxbai-embed-large-v1.
  6. Inizializzare il large language model usando la chiave API di Groq Cloud e il modello llama-3.1-70b-versatile.

Successivamente implementerà le seguenti funzioni Python:

  • load_files(): Questa funzione caricherà i file, li analizzerà con LlamaParser, li convertirà in embedding e li salverà nel vector store. Sarà incluso l'handling delle eccezioni per gestire casi in cui vengano caricati oggetti non file o formati non supportati.
  • respond(): Questa funzione prenderà l'input dell'utente, recupererà contenuti dal vector store e li userà per generare una risposta tramite il modello Groq. La generazione sarà in formato streaming e verrà gestita l'eccezione se non sono stati caricati file.

Infine, costruirà i componenti UI, inclusi un uploader di file, pulsanti, una chat box e l'interfaccia di chat complessiva.

Scopri di più sul framework LlamaIndex seguendo il tutorial più semplice su LlamaIndex.

Ecco lo script app.py:

import os

import gradio as gr
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex
from llama_index.embeddings.mixedbreadai import MixedbreadAIEmbedding
from llama_index.llms.groq import Groq
from llama_parse import LlamaParse

# API keys
llama_cloud_key = os.environ.get("LLAMA_CLOUD_API_KEY")
groq_key = os.environ.get("GROQ_API_KEY")
mxbai_key = os.environ.get("MXBAI_API_KEY")
if not (llama_cloud_key and groq_key and mxbai_key):
    raise ValueError(
        "API Keys not found! Ensure they are passed to the Docker container."
    )

# models name
llm_model_name = "llama-3.1-70b-versatile"
embed_model_name = "mixedbread-ai/mxbai-embed-large-v1"

# Initialize the parser
parser = LlamaParse(api_key=llama_cloud_key, result_type="markdown")

# Define file extractor with various common extensions
file_extractor = {
    ".pdf": parser,
    ".docx": parser,
    ".doc": parser,
    ".txt": parser,
    ".csv": parser,
    ".xlsx": parser,
    ".pptx": parser,
    ".html": parser,
    ".jpg": parser,
    ".jpeg": parser,
    ".png": parser,
    ".webp": parser,
    ".svg": parser,
}

# Initialize the embedding model
embed_model = MixedbreadAIEmbedding(api_key=mxbai_key, model_name=embed_model_name)

# Initialize the LLM
llm = Groq(model="llama-3.1-70b-versatile", api_key=groq_key)


# File processing function
def load_files(file_path: str):
    global vector_index
    if not file_path:
        return "No file path provided. Please upload a file."
   
    valid_extensions = ', '.join(file_extractor.keys())
    if not any(file_path.endswith(ext) for ext in file_extractor):
        return f"The parser can only parse the following file types: {valid_extensions}"

    document = SimpleDirectoryReader(input_files=[file_path], file_extractor=file_extractor).load_data()
    vector_index = VectorStoreIndex.from_documents(document, embed_model=embed_model)
    print(f"Parsing completed for: {file_path}")
    filename = os.path.basename(file_path)
    return f"Ready to provide responses based on: {filename}"


# Respond function
def respond(message, history):
    try:
        # Use the preloaded LLM
        query_engine = vector_index.as_query_engine(streaming=True, llm=llm)
        streaming_response = query_engine.query(message)
        partial_text = ""
        for new_text in streaming_response.response_gen:
            partial_text += new_text
            # Yield an empty string to cleanup the message textbox and the updated conversation history
            yield partial_text
    except (AttributeError, NameError):
        print("An error occurred while processing your request.")
        yield "Please upload the file to begin chat."


# Clear function
def clear_state():
    global vector_index
    vector_index = None
    return [None, None, None]


# UI Setup
with gr.Blocks(
    theme=gr.themes.Default(
        primary_hue="green",
        secondary_hue="blue",
        font=[gr.themes.GoogleFont("Poppins")],
    ),
    css="footer {visibility: hidden}",
) as demo:
    gr.Markdown("# DataCamp Doc Q&A 🤖📃")
    with gr.Row():
        with gr.Column(scale=1):
            file_input = gr.File(
                file_count="single", type="filepath", label="Upload Document"
            )
            with gr.Row():
                btn = gr.Button("Submit", variant="primary")
                clear = gr.Button("Clear")
            output = gr.Textbox(label="Status")
        with gr.Column(scale=3):
            chatbot = gr.ChatInterface(
                fn=respond,
                chatbot=gr.Chatbot(height=300),
                theme="soft",
                show_progress="full",
                textbox=gr.Textbox(
                    placeholder="Ask questions about the uploaded document!",
                    container=False,
                ),
            )

    # Set up Gradio interactions
    btn.click(fn=load_files, inputs=file_input, outputs=output)
    clear.click(
        fn=clear_state,  # Use the clear_state function
        outputs=[file_input, output],
    )

# Launch the demo
if __name__ == "__main__":
    demo.launch()
  • Esegui il file Python sopra per avviare il server Gradio con il seguente comando nel terminale:
$ python app.py  

Output:

Esecuzione dell'app Gradio in locale.

  • Puoi accedere all'interfaccia di Grodio copiando e incollando l'URL generato nel browser. Quindi puoi caricare un file e iniziare a fare domande al riguardo.

Accesso all'app Gradio dal browser.

Accesso all'app Gradio dal browser. Immagine dell'autore

In questo tutorial usiamo LlamaIndex per creare e distribuire la nostra applicazione LLM. Puoi creare un'app simile con LangChain seguendo il corso breve Sviluppare applicazioni LLM con LangChain.

3. Creazione del Dockerfile

  • Nel tuo progetto, crea un Dockerfile per impacchettare lo script dell'applicazione, le dipendenze Python e le configurazioni del server, inizializzando il server Gradio. 

Il Dockerfile eseguirà le seguenti attività:

  1. Impostare un ambiente Python 3.9.
  2. Definire la directory di lavoro.
  3. Copiare il file requirements.txt nella directory /app. Questo file contiene i nomi di tutti i pacchetti Python richiesti.
  4. Installare tutte le dipendenze specificate in requirements.txt.
  5. Copiare il file app.py nella directory /app.
  6. Esporre la porta e impostare l'URL del server Gradio.
  7. Eseguire il file dell'applicazione per avviare il server.

Ecco come dovrebbe apparire il Dockerfile:

# Dockerfile

# Use the official Python image with the desired version
FROM python:3.9-slim

# Set the working directory inside the container
WORKDIR /app

# Copy the requirements file to the working directory
COPY requirements.txt /app

# Install the dependencies
RUN pip install --no-cache-dir -r requirements.txt

# Copy the rest of the application code to the working directory
COPY app.py /app

# Expose the port that Gradio will run on (default is 7860)
EXPOSE 7860

ENV GRADIO_SERVER_NAME="0.0.0.0"

# Command to run your application
CMD ["python", "app.py"]
  • E così appare il file requirements.txt. Aggiungilo anche al tuo progetto:
gradio
llama-index-embeddings-mixedbreadai
llama-index-llms-groq
llama-index

4. Creazione dell'immagine Docker ed esecuzione del container

  • Digita il seguente comando nel terminale per costruire l'immagine docker docqa. Userà il Dockerfile per creare l'immagine Docker.
$ docker build -t docqa . 

Possiamo vedere i log dei processi in corso durante la creazione dell'immagine Docker:

creazione dell'immagine docker LLM

Creazione dell'immagine Docker LLM. Immagine dell'autore

  • Una volta creata l'immagine, vai su Docker Desktop, clicca sulla scheda Images e seleziona l'immagine Docker per vedere i log e le varie istruzioni per eseguirla. 

visualizzazione dell'immagine docker su Docker Desktop

Visualizzazione dell'immagine Docker su Docker Desktop. Immagine dell'autore

Ora eseguiremo il container Docker in locale usando l'immagine. Gli forniremo il numero di porta, un file .env per impostare le variabili d'ambiente, il nome del container Docker e il tag dell'immagine Docker.

  • Esegui il seguente comando nel tuo terminale: 
$ docker run -p 7860:7860 --env-file .env --name docqa-container docqa

Una volta avviato il container, puoi accedere all'app Gradio incollando l'URL, in questo caso http://0.0.0.1:7860/ nel browser. 

Test dell'applicazione LLM nel container docker.

Test dell'applicazione LLM nel container Docker. Immagine dell'autore

  • Per visualizzare le informazioni su tutti i container in esecuzione in locale, digita il seguente comando:
$ docker ps

Output:

CONTAINER ID   IMAGE     COMMAND           CREATED          STATUS          PORTS                    NAMES
ff2a11da13d7   docqa     "python app.py"   17 seconds ago   Up 16 seconds   0.0.0.0:7860->7860/tcp   docqa-container
  • Puoi fermare il container Docker con il comando stop:
$ docker stop docqa-container 
  • Puoi anche rimuoverlo con il comando rm:
$ docker rm docqa-container 

Una volta che abbiamo un'immagine Docker, possiamo distribuire la nostra applicazione LLM ovunque: GCP, AWS, Azure o qualsiasi server cloud che supporti la distribuzione con Docker.

5. Distribuire l'applicazione LLM su Hugging Face usando Docker

Per semplificare le cose ai principianti, distribuiremo l'app usando Docker su Hugging Face Cloud (Spaces). 

  • Vai alla dashboard di Hugging Face, clicca sull'immagine del profilo e seleziona + New Space.
  • Dai un nome al tuo Space, aggiungi una breve descrizione, seleziona la licenza e l'SDK, e crea il repository dello Space.

Creazione di un nuovo Hugging Face Space usando Docker

Creazione del nuovo Hugging Face Space usando Docker. Fonte immagine: Hugging Face

Una volta creato il repository dello Space, riceverai le istruzioni su come clonarlo e aggiungere i file necessari.

  • Per clonare il repository, usa il seguente comando (aggiorna l'URL con quello del tuo Space):
$ git clone https://huggingface.co/spaces/kingabzpro/doc-qa-docker
  • Copia e incolla tutti i file dalla directory del progetto nel nuovo repository:

Ecco come dovrebbe apparire la directory del progetto con tutti i file. Assicurati sempre di non fare push del file .env, quindi aggiungilo al .gitignore. 

Directory del progetto.

Struttura dei file del progetto. Immagine dell'autore

  • Metti in stage i file, fai il commit con un messaggio e poi fai push sullo Space di Hugging Face:
$ git add .                                                                                            
$ git commit -m "Deploying the App" 
$ git push

Output:

Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 16 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 7.60 KiB | 7.60 MiB/s, done.
Total 7 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://huggingface.co/spaces/kingabzpro/doc-qa-docker
   afb20ad..5ca6388  main -> main
  • Vai sul tuo Hugging Face Space per accedere all'applicazione. Costruirà l'immagine Docker e poi servirà l'applicazione:

Creazione dell'immagine docker nel cloud Hugging Face

Creazione dell'immagine Docker su Hugging Face Cloud. Fonte immagine: Doc Qa Docker

Se vedi un errore come quello sotto, non preoccuparti. È dovuto alla mancanza di variabili d'ambiente. Dobbiamo solo impostarle nello Space di Hugging Face.

Errore a runtime sull'app distribuita.

Errore a runtime sull'app distribuita. Fonte immagine: Doc Qa Docker

  • Per aggiungere una nuova variabile d'ambiente nel tuo Space, vai su Settings, scorri in basso e clicca sul pulsante New secret. Poi fornisci nome e valore per la variabile, come mostrato sotto. In questo caso, aggiungiamo le chiavi API necessarie:

aggiungere i secret per l'app distribuita.

Aggiunta dei secret all'app distribuita. Fonte immagine: Impostazioni Doc Qa Docker.

Ecco come dovrebbero apparire i tuoi secret dopo aver aggiunto tutte le chiavi API necessarie come variabili d'ambiente:

tutti i secret per l'app distribuita.

Secret per l'app distribuita. Fonte immagine: Impostazioni Doc Qa Docker.

Una volta impostati i secret, l'app si riavvierà automaticamente e dovresti vederla in esecuzione. Usala e goditi la tua applicazione di Q&A sui documenti nel cloud!

App LLM su Hugging Face Spaces.

App LLM su Hugging Face Spaces. Fonte: Doc Qa Docker

Per riprodurre i risultati, tutti i file e le configurazioni sono disponibili nel repository GitHub: kingabzpro/Deploy-Doc-QA.

6. Monitoraggio dell'applicazione distribuita

Usare servizi di AI ha vantaggi: non devi distribuire o gestire servizi, ottieni throughput elevato e hai una dashboard con i log. 

La tua dashboard LlamaCloud registra tutti i documenti che sono stati analizzati. Puoi consultare la cronologia o le richieste e confrontare l'utilizzo. 

Dashboard Llama Cloud

Dashboard Llama Cloud. Fonte: LlamaCloud 

Allo stesso modo, puoi anche verificare il numero di token usati per il modello di embedding e il numero di richieste generate. 

Dashboard Mixedbread

Dashboard Mixedbread. Fonte: Mixedbread

I log più dettagliati di ciascuna API si trovano su GroqCloud, con informazioni su latenza, numero di token, chiave AI e ID richiesta per effettuare il debug del sistema.

Log Groq Cloud

Log GroqCloud. Fonte: GroqCloud

Considerazioni finali

Questa guida ci ha mostrato come combinare più servizi per costruire un'applicazione di Q&A su documenti efficiente con un uso minimo di risorse e overhead computazionale. Tutti i servizi e gli strumenti utilizzati sono disponibili gratuitamente per testare e costruire la tua applicazione.

Abbiamo ridotto la dimensione dell'immagine Docker di 600 MB usando più servizi di AI pronti all'uso. Se avessimo distribuito tutto in autonomia, la dimensione sarebbe stata intorno ai 20 GB o più. 

Ti consiglio, come prossimo passo del tuo percorso di apprendimento, il corso Concetti di LLMOps: dall'ideazione alla distribuzione. Questo corso ti aiuterà a comprendere il ciclo di vita di sviluppo degli LLM e le sfide della distribuzione delle applicazioni. Ti insegnerà anche come applicare efficacemente questi concetti.


Abid Ali Awan's photo
Author
Abid Ali Awan
LinkedIn
Twitter

In quanto data scientist certificato, sono appassionato di sfruttare tecnologie all’avanguardia per creare applicazioni di machine learning innovative. Con una solida esperienza in riconoscimento vocale, analisi e reportistica dei dati, MLOps, AI conversazionale e NLP, ho affinato le mie competenze nello sviluppo di sistemi intelligenti in grado di avere un impatto concreto. Oltre alla mia expertise tecnica, sono anche un comunicatore efficace, con il talento di rendere chiari e sintetici concetti complessi. Di conseguenza, sono diventato un blogger molto seguito in ambito data science, condividendo idee ed esperienze con una community in crescita di professionisti dei dati. Attualmente mi concentro sulla creazione e sull’editing di contenuti, lavorando con large language model per sviluppare contenuti potenti e coinvolgenti che possano aiutare aziende e singoli a valorizzare al meglio i propri dati.

Argomenti
MLOps
Data Engineering

Approfondisci gli LLM con questi corsi!

Corso

Sviluppare applicazioni LLM con LangChain

3 ore
52K
Scopri come costruire applicazioni basate sull'intelligenza artificiale utilizzando LLM, prompt, catene e agenti in LangChain.
Vedi i dettagliRight Arrow
Inizia Il Corso
Mostra altroRight Arrow
Correlato

blog

Tokenizzazione nel NLP: come funziona, sfide e casi d'uso

Guida al preprocessing NLP nel machine learning. Copriamo spaCy, i transformer di Hugging Face e come funziona la tokenizzazione in casi d'uso reali.
Abid Ali Awan's photo

Abid Ali Awan

10 min

blog

Che cos'è Snowflake? Guida per principianti alla piattaforma dati cloud

Esplora le basi di Snowflake, la piattaforma dati cloud. Scopri la sua architettura, le sue funzionalità e come integrarla nelle tue pipeline di dati.
Tim Lu's photo

Tim Lu

12 min

blog

I 15 migliori server MCP remoti che ogni AI builder dovrebbe conoscere nel 2026

Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Abid Ali Awan's photo

Abid Ali Awan

15 min

Mostra AltroMostra Altro