File size: 6,529 Bytes
3fbe97b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | # Deployment Guide
This document covers all deployment options for Irminsul, the cost tradeoffs between them, and the architectural decisions behind the live demo setup.
---
## Deployment Options
Irminsul supports two LLM backends and multiple hosting targets. Choose based on your infrastructure and budget.
| Backend | Where to Run | GPU Required | Cost |
|---|---|---|---|
| **Groq** (recommended) | Anywhere β no GPU | No | Free tier available |
| **Local Llama** (fine-tuned model) | Local machine / GPU VM | Yes (6GB+ VRAM) | Hardware cost / ~$0.50β1.50/hr on Azure |
---
## Live Demo: HuggingFace Spaces + Groq
**Why this is the live demo environment:**
The fine-tuned Llama 3.1 8B model is 16GB on disk and requires a GPU-enabled instance to serve at acceptable latency. On Azure, the minimum viable GPU instance for this model is the **NC4as T4 v3** (~$0.50/hr, ~$360/month). Running this persistently for a portfolio project is not cost-effective.
The live demo instead uses:
- **HuggingFace Spaces** β free CPU hosting for the FastAPI container
- **Groq API** β runs `llama-3.3-70b-versatile` on Groq's Language Processing Units (LPUs) at ~300 tokens/second, for free under the public tier
This demonstrates the identical RAG architecture β the LLM backend is swapped via a single environment variable (`LLM_BACKEND=groq`). The retrieval pipeline, guardrails, response format, and API contract are unchanged.
```
Live demo: https://huggingface.co/spaces/MukulRay/Irminsul
```
---
## Option A: Local Development
The full stack including the fine-tuned model runs locally on an RTX 3060 6GB:
```bash
# 1. Clone and install
git clone https://github.com/MukulRay1603/Irminsul.git
cd Irminsul
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
# 2. Configure
cp .env.example .env
# Edit .env β set MODEL_PATH, PINECONE_API_KEY
# 3. Ingest corpus
python ingest.py --dir ./docs --chunk-size 300 --chunk-overlap 40
# 4. Serve
uvicorn main:app --host 0.0.0.0 --port 8000
```
**Memory profile:**
| Component | VRAM |
|---|---|
| Llama 3.1 8B @ 4-bit NF4 | ~4.5 GB |
| all-MiniLM-L6-v2 embedder | ~90 MB |
| Inference headroom | ~1.2 GB |
| **Total** | **~5.8 GB** |
The model loads with `max_memory={0: "5.5GiB", "cpu": "24GiB"}` β layers that don't fit on GPU overflow to RAM automatically via `accelerate`.
---
## Option B: Docker (Local or Any Cloud)
The Dockerfile is intentionally slim β the model is **not baked in**. It's injected at runtime via `MODEL_PATH`.
```bash
# Build
docker build -t irminsul:latest .
# Run with Groq backend (no GPU needed)
docker run -p 8000:8000 \
-e PINECONE_API_KEY=your_key \
-e GROQ_API_KEY=your_key \
-e PINECONE_INDEX=llmops-rag \
-e LLM_BACKEND=groq \
irminsul:latest
# Run with local model (GPU required)
docker run -p 8000:8000 \
--gpus all \
-v /path/to/models:/app/models \
-e PINECONE_API_KEY=your_key \
-e MODEL_PATH=/app/models/merged/exp2_lr2e-4_r16 \
-e LLM_BACKEND=local \
irminsul:latest
```
---
## Option C: Azure Container Apps
Azure Container Apps (ACA) is the production deployment target. The `deploy_azure.sh` script provisions the full stack in one command.
### Prerequisites
```bash
# Install Azure CLI
# macOS:
brew install azure-cli
# Linux:
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# Windows: https://aka.ms/installazurecliwindows
# Log in
az login
az account show # confirm your subscription
```
### One-shot deploy
```bash
export PINECONE_API_KEY=your_pinecone_key
export GROQ_API_KEY=your_groq_key
chmod +x deploy_azure.sh
./deploy_azure.sh
```
The script:
1. Creates resource group `irminsul-rg` in East US
2. Creates Azure Container Registry `irminsulacr`
3. Builds the Docker image via **ACR Tasks** β the source code is uploaded and built in Azure's cloud; no local Docker daemon needed
4. Creates a Container Apps environment
5. Deploys the app with secrets injected as environment variables
6. Outputs the live HTTPS URL
### Tearing down
```bash
# Delete everything β stops all billing immediately
az group delete --name irminsul-rg --yes --no-wait
```
### Cost breakdown (Groq backend, no GPU)
| Resource | SKU | Cost |
|---|---|---|
| Container Apps | Consumption plan | Free (180k vCPU-s/month) |
| ACR | Basic | ~$5/month |
| Outbound bandwidth | First 100GB | Free |
| **Total** | | **~$5/month** |
On Azure for Students ($100 credit), this runs for ~20 months.
### Why not GPU on Azure?
To serve the fine-tuned Llama model in production, a GPU instance is required:
| Instance | GPU | VRAM | Cost |
|---|---|---|---|
| NC4as T4 v3 | Tesla T4 | 16 GB | ~$0.50/hr = **~$360/month** |
| NC6s v3 | Tesla V100 | 16 GB | ~$0.90/hr = **~$648/month** |
At these prices, a portfolio project running 24/7 would exhaust the $100 student credit in under a week. The Groq backend delivers the same RAG functionality at zero marginal cost, making it the right engineering tradeoff.
### Serving the fine-tuned model on Azure (production path)
If cost were not a constraint, the correct architecture is:
1. **Upload model to Azure Blob Storage** (~$0.02/GB/month for 16GB = ~$0.32/month)
2. **Mount as a volume** in Container Apps β the container sees it at `/app/models/`
3. **Switch to GPU SKU** β replace `--cpu 1.0 --memory 2.0Gi` in `deploy_azure.sh` with a GPU-enabled workload profile
4. **Set `LLM_BACKEND=local`** in env vars
The Docker image and application code require zero changes for this path. The abstraction was designed for it.
---
## Environment Variables Reference
| Variable | Required | Default | Description |
|---|---|---|---|
| `PINECONE_API_KEY` | Yes | β | Pinecone serverless API key |
| `PINECONE_INDEX` | No | `llmops-rag` | Pinecone index name |
| `LLM_BACKEND` | No | `groq` | `groq` or `local` |
| `GROQ_API_KEY` | If Groq | β | Groq API key |
| `GROQ_MODEL` | No | `llama-3.3-70b-versatile` | Groq model name |
| `MODEL_PATH` | If local | `./models/merged/exp2_lr2e-4_r16` | Path to merged model |
| `EMBED_MODEL` | No | `sentence-transformers/all-MiniLM-L6-v2` | Embedding model |
---
## CI/CD (Planned)
The intended CI/CD pipeline:
```
git push main
β
βΌ
GitHub Actions
βββ Run tests
βββ Build Docker image
βββ Push to ACR
βββ az containerapp update --image new-tag
```
This would give zero-downtime rolling deploys on every push to main. Currently, re-running `deploy_azure.sh` achieves the same result with a cold start.
|