Cursus
Docker laat je consistente, draagbare en geïsoleerde omgevingen creëren, en is daarmee essentieel voor LLMOps (Large Language Models Operations). Door verschillende LLM-applicaties en hun afhankelijkheden in containers te encapsuleren, vereenvoudigt Docker de deployment, zorgt het voor compatibiliteit tussen systemen en stroomlijnt het testen.
In deze tutorial leer je hoe je een “document Q&A”-chatbot bouwt en met Docker naar de cloud deployt. We gebruiken Gradio voor de gebruikersinterface, LlamaIndex voor orkestratie, LlamaParse voor het parsen van documenten, Mixedbread AI voor embeddings, Groq voor toegang tot large language models, Docker voor het verpakken van de applicatie en afhankelijkheden, en Hugging Face Spaces om de applicatie in de cloud te deployen.
Deze tutorial is eenvoudig opgezet, zodat iedereen met beperkte kennis van AI-applicaties dit gratis kan bouwen.
Projectbeschrijving
Er zijn twee hoofdbenaderingen voor het ontwikkelen en deployen van AI-applicaties:
- Volledig open source: Deze aanpak legt de nadruk op privacy en gegevensbescherming.
- Volledig closed source: Deze methode omvat het integreren van meerdere API’s en clouddiensten.
Beide benaderingen hebben voor- en nadelen. In ons geval hebben we voor de tweede aanpak gekozen: het integreren van meerdere AI-diensten. Zo kunnen we een snelle AI-applicatie bouwen die slechts enkele seconden nodig heeft om te bouwen en te deployen. Onze hoofdprioriteit is het verkleinen van de Docker-image, wat effectief kan door meerdere AI-diensten te integreren.
Bekijk de tutorial Local AI with Docker, n8n, Qdrant, and Ollama om een LLM-app te bouwen met open-sourcetools en -frameworks voor betere privacy!
We bouwen een generieke Q&A-chatbot waarmee gebruikers documenten kunnen uploaden en er in realtime mee kunnen chatten. Dit lijkt sterk op Google’s NotebookLM.

Projectdiagram. Afbeelding door de auteur
Dit zijn de tools die we in dit project gebruiken:
- Gradio Blocks: Voor het bouwen van een interface waarmee gebruikers elk tekstdocument kunnen uploaden en er eenvoudig mee kunnen chatten.
- LlamaCloud: Voor het parsen van bestanden en het extraheren van tekstdata in markdown-stijl.
- MixedBread AI: Dit wordt gebruikt om geladen documenten en chatberichten om te zetten in embeddings voor context retrieval.
- Groq Cloud: Voor snelle LLM-antwoorden. In dit project gebruiken we het model llama-3.1-70b.
- LlamaIndex: Voor het bouwen van de RAG-pijplijn (Retrieval Augmented Generation) die alle AI-diensten orkestreert. De pijplijn gebruikt het geüploade bestand en gebruikersberichten om contextbewuste antwoorden te genereren.
- Docker: Voor het encapsuleren van de app, dependencies, omgeving en configuraties.
- Hugging Face Cloud: We pushen alle bestanden naar de Spaces-repository; Hugging Face bouwt automatisch de image via de Dockerfile en deployt die naar de server.
Ben je nieuw met LLM’s? Volg dan de course Master Large Language Models (LLMs) Concepts om de basisbegrippen, methodologieën, ethische overwegingen en het laatste onderzoek te leren kennen.
1. De omgeving instellen
Voordat we de LLM-app bouwen, moeten we Docker downloaden en installeren vanaf de officiële website.
- Installeer Docker op je lokale systeem met de standaardopties.
- Maak vervolgens een projectmap in je favoriete IDE en voeg een
.env-bestand toe. We gebruiken dit bestand om de API-sleutels voor LlamaCloud, MixedBread AI en Groq Cloud op te slaan. - Meld je daarna aan bij LlamaCloud en genereer je API-sleutel. We gebruiken LlamaCloud om diverse tekstformaten te parsen, waaronder Excel, txt, Word en PDF’s.

Een nieuwe sleutel genereren in LlamaCloud. Bron: LlamaCloud
- Meld je aan bij MixedBread AI en genereer je API-sleutel. Met deze sleutel krijgen we gratis toegang tot hun topklasse embeddingmodel.

Een API-sleutel aanmaken in MixedBread. Bron: MixedBread
- Ga naar GroqCloud en meld je aan om gratis je API-sleutel te genereren. We gebruiken GroqCloud om high-speed LLM’s te benaderen.

Een API-sleutel aanmaken in GroqCloud. Bron: GroqCloud
Leer alles over GroqCloud in het artikel over de Groq LPU Inference Engine. Je ontdekt de Groq API en functies met codevoorbeelden. Leer bovendien hoe je contextbewuste AI-applicaties bouwt met de Groq API en LlamaIndex.
Zo zou je .env-bestand eruit moeten zien:
LLAMA_CLOUD_API_KEY=llx-XXXXXX
GROQ_API_KEY=gsk_XXXXXXX
MXBAI_API_KEY=emb_XXXXXX
Vergeet niet het .env-bestand toe te voegen aan je .gitignore om te voorkomen dat je per ongeluk je API-sleutels openbaar maakt.
2. De LLM-applicatie bouwen
We maken nu een Python-script genaamd app.py en voegen de UI-componenten toe, terwijl we alle AI-diensten integreren met LlamaParser om de Retrieval-Augmented Generation (RAG)-pijplijn met LlamaIndex te ontwikkelen.
Het script app.py doet het volgende:
- Alle benodigde Python-packages laden.
- Alle API-sleutels veilig laden vanuit het
.env-bestand. - De LlamaParser initialiseren met de LlamaCloud API-sleutel.
- Een file-extractor definiëren die verschillende gangbare extensies aankan.
- Het embeddingmodel initialiseren met de MixedBread AI API-sleutel, specifiek het model
mixedbread-ai/mxbai-embed-large-v1. - Het large language model initialiseren met de Groq Cloud API-sleutel en het model
llama-3.1-70b-versatile.
Vervolgens implementeert het de volgende Python-functies:
load_files(): Deze functie laadt de bestanden, parsed ze met LlamaParser, zet ze om in embeddings en slaat ze op in de vector store. Er is foutafhandeling voor gevallen waarin niet-bestanden of niet-ondersteunde formaten worden geüpload.respond(): Deze functie neemt gebruikersinvoer, haalt content op uit de vector store en gebruikt dat om een antwoord te genereren met het Groq-model. De respons wordt gestreamd, en er is foutafhandeling als er geen bestanden zijn geüpload.
Tot slot worden de UI-componenten gebouwd, waaronder een bestandsuploader, knoppen, een chatvenster en de complete chatinterface.
Leer meer over het LlamaIndex-framework met de toegankelijke LlamaIndex-tutorial.
Hier is het app.py-script:
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()
- Voer het bovenstaande Python-bestand uit om de Gradio-server te starten met de volgende opdracht in je terminal:
$ python app.py
Output:

- Je kunt de Gradio-UI openen door de gegenereerde URL te kopiëren en te plakken in de browser. Upload vervolgens een bestand en stel er vragen over.

De Gradio-app openen in de browser. Afbeelding door de auteur
In deze tutorial gebruiken we LlamaIndex om onze LLM-app te bouwen en te deployen. Je kunt een vergelijkbare app maken met LangChain via de short course Developing LLM Applications with LangChain.
3. De Dockerfile maken
- Maak in je project een
Dockerfileom het applicatiescript, Python-afhankelijkheden en serverconfiguraties te verpakken en de Gradio-server te initialiseren.
De Dockerfile voert het volgende uit:
- Een Python 3.9-omgeving opzetten.
- De werkmap definiëren.
- Het bestand
requirements.txtkopiëren naar de/app-map. Dit bestand bevat alle vereiste Python-packages. - Alle dependencies in
requirements.txtinstalleren. - Het bestand
app.pykopiëren naar de/app-map. - De poort exposen en de Gradio-server-URL instellen.
- Het applicatiebestand uitvoeren om de server te starten.
Zo zou de Dockerfile eruit moeten zien:
# 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"]
- En zo ziet het bestand
requirements.txteruit. Voeg dit ook toe aan je project:
gradio
llama-index-embeddings-mixedbreadai
llama-index-llms-groq
llama-index
4. De Docker-image bouwen en de container draaien
- Typ de volgende opdracht in de terminal om de
docqa-dockerimage te bouwen. Deze gebruikt deDockerfileom de image te maken.
$ docker build -t docqa .
Je ziet de logs van de processen die plaatsvinden tijdens het bouwen van de Docker-image:

De LLM Docker-image bouwen. Afbeelding door de auteur
- Zodra de image succesvol is gebouwd, ga je in Docker Desktop naar het tabblad Images en klik je op de Docker-image om de logs en instructies voor het draaien te bekijken.

De Docker-image bekijken in Docker Desktop. Afbeelding door de auteur
We draaien nu lokaal de Docker-container met de image. We geven het poortnummer mee, een .env-bestand voor de omgevingsvariabelen, de containenaam en de imagetag.
- Voer de volgende opdracht uit in je terminal:
$ docker run -p 7860:7860 --env-file .env --name docqa-container docqa
Zodra de container draait, kun je de Gradio-app openen door de URL, in dit geval http://0.0.0.1:7860/, in de browser te plakken.

De LLM-applicatie in de Docker-container testen. Afbeelding door de auteur
- Om informatie te zien over alle lokaal draaiende containers, typ je de volgende opdracht:
$ 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
- Je kunt de Docker-container stoppen met het commando
stop:
$ docker stop docqa-container
- Je kunt hem ook verwijderen met het commando
rm:
$ docker rm docqa-container
Zodra we een Docker-image hebben, kunnen we onze LLM-app overal deployen: GCP, AWS, Azure of elke cloudserver die Docker ondersteunt.
5. De LLM-applicatie met Docker naar Hugging Face deployen
Om het voor beginners eenvoudig te houden, deployen we de app met Docker op Hugging Face Cloud (Spaces).
- Ga naar het Hugging Face-dashboard, klik op je profielfoto en kies + New Space.
- Geef je Space een naam, voeg een korte beschrijving toe, selecteer de licentie en SDK, en maak de Space-repository aan.

Een nieuwe Hugging Face Space maken met Docker. Bron: Hugging Face
Zodra de Space-repository is aangemaakt, krijg je instructies om deze te clonen en de benodigde bestanden toe te voegen.
- Gebruik de volgende opdracht om de repository te clonen (werk de URL bij naar die van jouw Space):
$ git clone https://huggingface.co/spaces/kingabzpro/doc-qa-docker
- Kopieer en plak alle bestanden uit de projectmap naar de nieuwe repository:
Zo ziet je projectmap eruit met alle bestanden. Zorg er altijd voor dat je het .env-bestand niet pusht; zet het in de .gitignore.

Projectbestandsstructuur. Afbeelding door de auteur
- Stage de bestanden, commit met een bericht en push ze naar de Hugging Face Space:
$ 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
- Ga naar je Hugging Face Space om de applicatie te openen. De Docker-image wordt gebouwd en daarna wordt de app geserveerd:

De Docker-image bouwen op de Hugging Face Cloud. Bron: Doc Qa Docker
Zie je een fout zoals hieronder, maak je dan geen zorgen. Dit komt door ontbrekende omgevingsvariabelen. We hoeven die variabelen alleen maar in te stellen in de Hugging Face Space.

Runtime-fout in de gedeployde app. Bron: Doc Qa Docker
- Om een nieuwe omgevingsvariabele toe te voegen aan je Space, ga je naar Settings, scrol je naar beneden en klik je op New secret. Geef vervolgens de naam en waarde op, zoals hieronder. In dit geval voegen we de benodigde API-sleutels toe:

Secrets toevoegen aan de gedeployde app. Bron: Doc Qa Docker settings.
Zo zien je secrets eruit nadat je alle benodigde API-sleutels als omgevingsvariabelen hebt toegevoegd:

Secrets voor de gedeployde app. Bron: Doc Qa Docker settings.
Zodra je de secrets hebt ingesteld, herstart de app automatisch en zou je de app moeten zien draaien. Gebruik ’m en veel plezier met je document-Q&A-applicatie in de cloud!

LLM-app op Hugging Face Spaces. Bron: Doc Qa Docker
Om de resultaten te reproduceren, vind je alle bestanden en configuraties in de GitHub-repository: kingabzpro/Deploy-Doc-QA.
6. De gedeployde applicatie monitoren
Het gebruik van AI-diensten heeft voordelen: je hoeft zelf geen services te deployen of beheren, je krijgt hoge throughput en een dashboard met logs.
Je LlamaCloud-dashboard logt alle documenten die zijn geparset. Je kunt de geschiedenis bekijken of gebruik vergelijken.

Llama Cloud-dashboard. Bron: LlamaCloud
Evenzo kun je ook het aantal tokens bekijken dat we hebben gebruikt voor het embeddingmodel en het aantal gegenereerde verzoeken.

Mixedbread-dashboard. Bron: Mixedbread
De meest gedetailleerde logs van elke API vind je op GroqCloud, met informatie over latency, het aantal tokens, de AI-sleutel en het request-ID om je systeem te debuggen.

GroqCloud-logs. Bron: GroqCloud
Tot slot
In deze gids hebben we geleerd hoe je meerdere diensten combineert om een efficiënte document-Q&A-app te bouwen met minimale resource- en rekenoverhead. Alle gebruikte services en tools zijn gratis beschikbaar, zodat je je eigen applicatie kunt testen en bouwen.
We hebben onze Docker-image met 600 MB verkleind door meerdere kant-en-klare AI-diensten te gebruiken. Als we alles zelf hadden gedeployd, zou de image circa 20 GB of meer zijn geweest.
Als volgende stap raad ik de course LLMOps Concepts: From Ideation to Deployment aan. Deze course helpt je inzicht te krijgen in de LLM-ontwikkelingscyclus en de uitdagingen bij het deployen van applicaties. Je leert ook hoe je deze concepten effectief toepast.
Als gecertificeerd data scientist haal ik met passie het maximale uit de nieuwste technologie om innovatieve machinelearning-toepassingen te bouwen. Met een sterke achtergrond in spraakherkenning, data-analyse en -rapportage, MLOps, conversationele AI en NLP heb ik mijn vaardigheden aangescherpt in het ontwikkelen van intelligente systemen die echt impact maken. Naast mijn technische expertise ben ik ook een sterke communicator met een talent om complexe concepten terug te brengen tot heldere, beknopte taal. Daardoor ben ik uitgegroeid tot een veelgelezen blogger over data science, waar ik mijn inzichten en ervaringen deel met een groeiende community van data-professionals. Op dit moment richt ik me op contentcreatie en redactie, waarbij ik met large language models werk aan krachtige en aansprekende content die zowel bedrijven als individuen helpt het beste uit hun data te halen.

