Serie: Self-Hosted LLMs für Datensouveränität | Code: GitHub

In Post 8 haben wir Llama-3.1-8B als self-hosted Judge evaluiert: 65% Agreement mit Claude Sonnet 4.5, klare Grenzen bei nuancierten B/C-Ratings. Die Frage blieb offen: Wie viel besser ist ein 8.75× größeres Model?

Der ursprüngliche Plan: Llama-70B auf AWS g5.12xlarge (4× A10G GPUs). Die Realität: Frankfurt komplett ausverkauft, Service Quotas zu niedrig, Wartezeit unbestimmt.

Die Alternative: Llama-3.1-70B lokal auf Mac Studio Max (M4 Max, 64 GB Unified Memory). Kein Deployment, keine Quota-Requests, kein Hourly Billing.

Und nebenbei: Die nächste Stufe der Data Sovereignty. Von self-hosted LLMs auf Cloud-Infrastruktur (Posts 1-8) zu komplett on-premise - keine Daten bei AWS, GCP oder anderen Cloud Providern.

Die Frage: Funktioniert das überhaupt? Und wie schnell kann es wirklich sein?

Spoiler: Ja - und überraschend. Mit optimiertem GPU Offloading: 20 Minuten Runtime für 170 Samples. Schneller als Cloud end-to-end (inkl. 15min Setup). 70% Agreement (vs 64% bei 8B), 6× bessere B-Detection, praktisch nutzbar.

Wichtig: Dieser Post fokussiert sich auf Inference Performance (LLM-as-Judge Evaluations). Training kommt in Post 9.


TL;DR – Für eilige Leser

Setup: Llama-3.1-70B-Q4 via Ollama auf Mac Studio Max (M4 Max, 64 GB RAM), 170 identische Samples wie Post 8

Ergebnisse:

Judge Agreement A-Ratings B-Ratings C-Ratings
Claude Sonnet 4.5 - 110 (64.7%) 50 (29.4%) 10 (5.9%)
Llama-3.1-70B 70.0% 145 (85.3%) 19 (11.2%) 6 (3.5%)
Llama-3.1-8B 64.1% 166 (97.6%) 3 (1.8%) 1 (0.6%)

Kernerkenntnisse:

  • +5.9pp Agreement vs 8B – statistisch signifikante Verbesserung
  • 6× bessere B-Detection (11.2% vs 1.8%)
  • ~60-75% C-Detection nach manueller Validierung (Claude hatte 2 False Positives)
  • 20min Runtime, schneller als Cloud – mit optimiertem GPU Offloading (num_gpu: 81)
  • $0 Cost, vollständige Data Sovereignty – komplett on-premise, keine Daten bei Cloud Providern
  • ⚠️ Immer noch 15pp unter Claude – kein Drop-in Replacement
  • ⚠️ Optimistic Bias bleibt – 85% A-Ratings, immer noch 20pp über Claude

Empfehlung: Llama-70B auf Apple Silicon mit optimiertem Setup ist schneller als Cloud end-to-end für kurze/mittlere Jobs. Für Production Quality Control: Commercial Judge oder noch größere Modelle.


Inhaltsverzeichnis


AWS sagt Nein: Die Capacity-Realität

Der Plan war simpel: g5.12xlarge Node Group in EKS, vLLM Deployment, 171 Samples in ~10 Minuten evaluieren.

Die Realität:

Launching a new EC2 instance. Status Reason: Could not launch On-Demand Instances. 
InsufficientInstanceCapacity - We currently do not have sufficient g5.12xlarge 
capacity in the Availability Zone you requested (eu-central-1b).

Versuch 2: eu-central-1a, eu-central-1c – gleicher Fehler.

Versuch 3: Service Quota Increase für g5.24xlarge (96 vCPUs statt 48) – 1-3 Werktage Wartezeit, ~$10/h statt ~$5.67/h (g5.12xlarge).

Versuch 4: Spot Instances – benötigt ebenfalls Quota Increase, und erfahrungsgemäß noch schlechter verfügbar als On-Demand.

Der Moment der Erkenntnis: Frankfurt ist ausverkauft. Wir können warten, andere Regionen probieren, oder… einen anderen Weg finden.


Apple Silicon als Alternative

Verfügbare Hardware: Mac Studio Max mit M4 Max Chip, 64 GB Unified Memory.

Die Frage: Reicht das für Llama-3.1-70B (70.5B Parameter)?

Model Size Check (mit Default 131k Context):

  • Llama-70B-Q4 (INT4 Quantization): ~40 GB
  • KV Cache (131k Context): ~40 GB → Zu viel!
  • Compute Graph (131k Context): ~16 GB
  • System + macOS: ~8-12 GB
  • Total (131k Context): ~104-108 GB ❌ Passt nicht in 64 GB

Die Lösung: Context Size drastisch reduzieren.

Judge Tasks brauchen wenig Context:

  • System Prompt: ~500 tokens
  • Chunk: ~200 tokens
  • Question + Answer: ~100 tokens
  • Total Input: ~800 tokens ← 4k Context reicht locker!

Mit 4k Context:

  • Model: 39.6 GB
  • KV Cache: ~1.3 GB (statt 40 GB!)
  • Compute Graph: ~0.6 GB (statt 16.3 GB bei 131k Context!)
  • Total: ~41.5 GB ✅ Passt locker in 64 GB mit entsprechendem Headroom

Setup: Llama-70B auf Mac Studio Max

Ollama Installation & Model Creation

Wichtig: Ollama läuft als Server - alle Commands kommunizieren über http://localhost:11434.

# 1. Ollama installieren
brew install ollama

# 2. Server starten (in eigenem Terminal, läuft dauerhaft)
ollama serve

# 3. In neuem Terminal: Base Model pullen (40 GB Download, ~60 Minuten)
ollama pull llama3.1:70b-instruct-q4_K_M

# 4. Modelfile für 4k Context erstellen
cat > Modelfile-llama70b-4k << 'EOF'
FROM llama3.1:70b-instruct-q4_K_M
PARAMETER num_ctx 4096
PARAMETER num_gpu 81     
EOF

# 5. Model mit kleinem Context erstellen
ollama create llama3.1-70b-4k -f Modelfile-llama70b-4k

Wichtig: num_gpu 81 lädt alle 81 Transformer Layers auf Metal (Apple GPU). Bei initialen Tests hatten wir aus Versehen nur 34 Layers auf GPU geladen - explizites Setzen auf 81 brachte 140% Performance-Gewinn (siehe Performance-Section). Der Default von -1 (auto) hat in unseren Tests auch funktioniert.

Memory Breakdown (tatsächlich, 4k Context):

Model Weights: 39.6 GB (CPU + Metal)
KV Cache: 1.3 GB (4k Context)
Compute Graph: 0.6 GB
Total: ~41.5 GB von 64 GB (22.5 GB frei für System u.a.)

Evaluation Script

Identischer Judge-Prompt wie Post 8, angepasst für Ollama API:

# llm_as_judge_ollama.py
response = requests.post(
    f"{ollama_url}/api/generate",
    json={
        "model": "llama3.1-70b-4k",
        "prompt": combined_prompt,
        "stream": False,
        "options": {
            "temperature": 0.0,    # Identisch zu Post 8 (Claude) für fairen Vergleich
            "num_predict": 300     # Identisch zu Post 8 (Claude) für fairen Vergleich
        }
    }
)

170 Samples (eine missing im Merge):

python3 llm_as_judge_ollama.py \
  --samples all_samples_60x3.jsonl \
  --output llama70b_results.jsonl \
  --model llama3.1-70b-4k

Runtime: 20 Minuten (~7 Sekunden pro Sample)


Ergebnisse: 70% Agreement, 6× bessere Detection

Overall Agreement

Vergleich Agreement Verbesserung
Claude vs Llama-70B 70.0% (119/170) +5.9pp vs 8B
Claude vs Llama-8B 64.1% (109/170) Baseline
Llama-8B vs Llama-70B 87.1% (148/170) Beide immer noch optimistischer als Claude

70% Agreement ist signifikant besser, aber immer noch 15 Prozentpunkte unter einem idealen Drop-in Replacement.

Rating Verteilung

Movement Richtung Claude:

Claude:     ████████████████████████████████ 64.7% A
            ████████████ 29.4% B
            ██ 5.9% C

Llama-70B:  ██████████████████████████████████████████ 85.3% A
            ████ 11.2% B
            █ 3.5% C

Llama-8B:   ████████████████████████████████████████████████ 97.6% A
            █ 1.8% B
            █ 0.6% C

70B findet mehr Probleme als 8B:

  • B-Detection: 19 vs 3 → 6× besser
  • C-Detection: 6 vs 1 → 6× besser

Aber immer noch deutlich optimistischer als Claude.

Detection Rates (roh)

B-Rating Detection (Speculation):

  • Claude identifiziert: 50 Samples
  • Llama-70B findet: 19 davon → 38% Detection Rate
  • Llama-8B findet: 3 davon → 6% Detection Rate

C-Rating Detection (Hallucinations, vor manueller Validierung):

  • Claude identifiziert: 10 Samples
  • Llama-70B findet: 6 davon (60%)
  • Llama-70B missed: 4 davon
  • Aber: Manuelle Validierung zeigt anderes Bild!

Manuelle Validierung: Die 7 False Negatives

Die kritische Frage: Sind die 4 gemissten C-Ratings wirklich Hallucinations?

Methodik: Alle 7 Fälle wo Claude C gab aber Llama-70B nicht (4× A, 3× B) manuell reviewt.

Ergebnis:

Kategorie Count Details
Claude False Positive 2 Zu streng, Answer ist OK
Grenzfall 1 B (Llama) könnte akzeptabel sein
True Hallucination 4 Claude hat Recht, Llama übersah sie

Revidierte C-Detection:

  • Claude’s 10 C-Ratings: ~7-8 echte Hallucinations (2 False Positives)
  • Llama-70B fand: 6 C-Ratings
  • Echte Detection Rate: ~60-75% (nicht die rohen 60%)

Beispiel: Claude False Positive

Chunk:

Prices are the same across all regions.

Question: “In which AWS regions are prices identical?”

Answer: “Prices are identical across all AWS regions.”

Claude: C – “Answer adds ‘AWS regions’ which is not mentioned in the chunk. The chunk only states ‘all regions’ without specifying AWS, making this a hallucination of specific context not present in the source material.”

Llama-70B: A – “Answer is strictly based on the chunk content, rephrasing it accurately without adding any new information.”

Manuelles Review: ✅ Llama hat Recht. Die Antwort übernimmt “AWS regions” aus der Frage (nicht erfunden), kombiniert mit “all regions” aus dem Chunk. Das ist kontextuelle Präzisierung, keine Hallucination. Claude interpretiert “strictly based on chunk” zu rigide.

Learning: Judge-Prompts müssen differenzieren zwischen echter Hallucination (Info erfunden) und kontextueller Präzisierung (Kontext aus Frage + Info aus Chunk).

Beispiel: True Hallucination (Llama missed)

Question: “Can you reserve Amazon MQ instances?”

Answer: “Reserved instances are available for long-term workloads.”

Chunk: “No, Amazon MQ does not offer reserved instance pricing.”

Claude: C – “Answer contradicts chunk, says reserved instances available when chunk says no”

Llama-70B: A – “Answer based on chunk content”

Manuelles Review: ✅ Claude hat Recht, klare Hallucination.

Learning: Llama-70B übersieht manchmal direkte Widersprüche.


Performance: GPU Offloading als Game Changer

Speed Comparison

vLLM (4× A10G, AWS g5.12xlarge):

  • Throughput: ~50-70 tokens/sec
  • Pro Sample: ~2-3 Sekunden
  • 170 Samples: ~5-9 Minuten
  • Cost: ~$5.67/Stunde = ~$1 für Test

Anmerkung: Diese Zahlen sind basierend auf Erfahrungswerten mit vLLM auf ähnlichen GPU-Setups (Posts 5-7), nicht auf g5.12xlarge getestet da keine Capacity verfügbar war.

Ollama (M4 Max, Mac Studio) - Optimiert:

  • Throughput: ~20 tokens/sec
  • Pro Sample: ~7 Sekunden
  • 170 Samples: ~20 Minuten
  • Cost: $0

Ratio: vLLM ist ~2-× schneller (reine Inference-Zeit).

GPU Offloading: Der kritische Parameter

Was passierte bei initialen Tests:

Llama-3.1-70B hat 81 Transformer Layers. Bei der ersten Model-Erstellung wurden nur 34 Layers auf Metal geladen.

Initiale Tests (Auto-Detection):

num_gpu: 34/81 Layers (42% GPU Offloading)
→ 58% der Layers auf CPU
→ Runtime: 48min
→ Throughput: ~8 tokens/sec

Warum nur 34? Unser Fehler:

  • Wir waren zu konservativ.
  • Wollten OOM vermeiden.

Memory-Analyse zeigte Potenzial:

  • Activity Monitor: 22.5 GB freier RAM (von 64 GB)
  • Unified Memory: GPU kann mehr System RAM nutzen
  • CPU-Layers sind der Bottleneck (~5-10× langsamer als Metal!)

Optimization:

cat > Modelfile-optimized << 'EOF'
FROM llama3.1:70b-instruct-q4_K_M
PARAMETER num_ctx 4096
PARAMETER num_gpu 81  # Alle Layers auf Metal!
EOF

ollama create llama3.1-70b-4k -f Modelfile-optimized

Ergebnis (Optimiert):

num_gpu: 81/81 Layers (100% GPU Offloading)
→ 0% auf CPU
→ Runtime: 20min ✅ (2.4× schneller!)
→ Throughput: ~20 tokens/sec (2.5× schneller!)
→ Memory: Stabil bei ~54 GB (kein Swap-Stress)

Learning: CPU-Fallback für 58% der Layers kostete 28 Minuten (140% Overhead). GPU Offloading ist ein kritischer Performance-Parameter für Apple Silicon. Maximale Layers austesten!

End-to-End Zeiten in der Praxis

Die 2-4× Speed-Differenz gilt nur für reine Inference-Zeit. Real-world ist komplexer:

Scale-to-Zero Cloud (Argo/EKS):

  • Node Startup: ~5-8 min
  • Pod + Model Download: ~5-8 min
  • Warmup: ~1-2 min
  • Setup-Overhead: ~15 min (wenn Capacity verfügbar!)

Für unseren Use Case (170 Samples):

  • Cloud end-to-end: ~15min + 10min = ~25min
  • Mac end-to-end: 0min + 20min = 20min
  • Mac ist schneller! 🚀 *Außer beim ersten Mal, wenn das Modell heruntergeladen werden muss.

ABER: Capacity ist nicht garantiert.

Wie wir am Anfang gesehen haben: Frankfurt komplett ausverkauft. In solchen Fällen:

  • Quota Increase beantragen: +1-3 Werktage + ggf. teurere Instanz (g5.24xlarge $10/h vs g5.12xlarge $5.67/h)
  • Andere Region probieren: +Setup-Zeit + höhere Latenz
  • Spot Instances: Noch schlechter verfügbar, können jederzeit terminiert werden
  • Warten auf Capacity: Unbestimmt

Mac Studio: Immer verfügbar. Kein Warten, kein Quota-Management, kein “InsufficientCapacity”. $0/h.

Trade-offs:

  • Kurze/mittlere Jobs (<2h): Mac schneller end-to-end, $0 vs $5.67-10/h, garantierte Verfügbarkeit
  • Marathon Jobs (>5h): Cloud Setup irrelevant, 4× Speed-Differenz dominiert, aber Kosten akkumulieren
  • Iterative Development: Mac gewinnt massiv - kein 15min Setup bei jedem Run, keine hourly charges
  • Verfügbarkeit: Mac gewinnt - keine Capacity-Probleme, keine Quota-Requests

Warum überraschend schnell?

Unified Memory Advantage:

  • CPU + GPU teilen 64 GB RAM
  • GPU kann bis zu ~40 GB für Model Layers nutzen
  • Alle 81 Layers passen auf Metal (mit 4k Context!)
  • Memory Bandwidth: ~400 GB/s (weniger als dedicated VRAM, aber ausreichend)

Metal Optimizations:

  • Apple Metal gut optimiert für Llama-Architektur (seit M1)
  • INT4 Quantization native supported
  • Aggressive GPU Offloading möglich dank Unified Memory

Der CPU-Bottleneck Killer:

  • Mit konservativen Settings: 58% Layers auf CPU → 48min
  • Mit optimiert: 0% Layers auf CPU → 20min
  • CPU-Fallback kostet 140% Performance!

Trade-off Analyse

Wann macht Apple Silicon Sinn:

Pros:

  • Vollständige Data Sovereignty – wenn auch die Datenhaltung 100% souverän sein muss, keine Daten bei Cloud - Providern
  • Kurze/mittlere Jobs (<2h) – Mac ist schneller end-to-end (20min vs 25min Cloud inkl. Setup)
  • Iterative Development – Kein 15min Setup bei jedem Run, 20min statt 25min für Tests
  • Cost-sensitive Use Cases – $0 vs $20-50+ AWS (je nach Laufzeit)
  • Capacity-Engpässe – Immer verfügbar, keine Quota-Requests
  • Unvorhersehbare Workloads – Keine Wartezeit, sofort einsatzberei

Cons:

  • Marathon Jobs (>5h) – Bei sehr langen Jobs wird Cloud Setup irrelevant, 4× Speed-Gap dominiert
  • Team Collaboration – Shared Cloud-Infra besser für mehrere Nutzer gleichzeitig
  • Extreme Throughput – Für 1000+ Samples pro Stunde braucht’s Cloud-Scale

Für diesen Test: Ideal. 20min statt 25min, $0 statt $1-2, garantierte Verfügbarkeit, und vollständige Data Sovereignty.


Die Hybride Strategie

Für Production könnte das funktionieren:

1. Llama-70B Pre-Filter (lokal)
   ↓ Findet ~60-75% der Probleme
   ↓ Cost: $0
   
2. Claude Final Review (Cloud)
   ↓ Nur auf flagged Samples (~15%)
   ↓ Cost: 85% Reduktion vs Full Claude
   
3. Manual Spot-Check (10%)
   ↓ Ground Truth Validation

Best of Both Worlds: Cost-Efficiency + Quality Assurance.

Wichtiger Caveat für Data Sovereignty:
Diese hybride Strategie sendet ~15% der Samples an Claude (Cloud). Wenn vollständige Data Sovereignty erforderlich ist:

  • Option A: Nur anonymisierte/synthetische Test-Daten an Claude senden
  • Option B: Komplett on-premise bleiben (70B + manuelle Reviews statt Claude)

Trade-off: Quality vs. Data Sovereignty muss bewusst entschieden werden.


Code & Resources

GitHub Repository: self-hosted-llms-tutorial

Scripts für diesen Post:

Setup Llama-70B auf Apple Silicon

# 1. Ollama installieren
brew install ollama

# 2. Server starten (in eigenem Terminal)
ollama serve

# 3. In neuem Terminal: Base Model laden
ollama pull llama3.1:70b-instruct-q4_K_M

# 4. Model mit 4k Context UND optimiertem GPU Offloading erstellen
cat > Modelfile << 'EOF'
FROM llama3.1:70b-instruct-q4_K_M
PARAMETER num_ctx 4096
PARAMETER num_gpu 81
EOF

ollama create llama3.1-70b-4k -f Modelfile

# 5. Evaluation laufen lassen (in weiterem Terminal)
python3 llm_as_judge_ollama.py \
  --samples your_samples.jsonl \
  --output results.jsonl \
  --model llama3.1-70b-4k

Requirements: Mac mit Apple Silicon (M1/M2/M3/M4), mindestens 64 GB RAM

Wichtig: num_gpu 81 lädt alle Layers auf Metal. Auto-Detection (num_gpu: -1, default) hat in unseren Tests auch funktioniert. Sie richtige Einstellung verhindert Performance-Verlust!


Fazit

Llama-3.1-70B auf Apple Silicon ist keine Notlösung, sondern eine überraschend starke Alternative - schneller als Cloud für typische Use Cases, $0 Cost, und vollständige Data Sovereignty.

Was wir erreicht haben:

  • 70% Agreement – messbar besser als 8B, aber unter Commercial Judges
  • ~60-75% Hallucination Detection nach manueller Validierung
  • 20min Runtime – schneller als Cloud end-to-end (inkl. 15min Setup)
  • $0 Cost, volle Data Sovereignty – komplett on-premise, keine Daten bei Cloud Providern (nächste Stufe nach self-hosted auf AWS)
  • Empirisch validiert – 170 Samples + manuelle Review der Critical Cases

Die klaren Grenzen:

  • Kein Production Quality Control – 70% Agreement reicht nicht für Final QC
  • Performance-Gap bei Marathon Jobs – bei >5h Jobs wird Cloud Setup irrelevant, 4× Speed-Gap dominiert
  • Optimistic Bias bleibt – immer noch zu optimistisch vs Claude
  • Prompt-sensitive – direkte Widersprüche manchmal übersehen

Was wir gelernt haben:

  1. Model Size hilft, aber ist keine Silver Bullet – 8.75× größer ≠ 8.75× besser
  2. Consumer Hardware mit richtiger Config ist stark – schneller als Cloud für Jobs <2h, garantierte Verfügbarkeit, aber: GPU Offloading kritisch!
  3. Manuelle Validierung ist essentiell – auch Claude macht Fehler (2/10 False Positives)
  4. Hybride Strategien möglich, aber Trade-off – 70B Pre-Filter + Claude Final Review = Cost-Efficiency + Quality, aber nur mit anonymisierten Daten wenn Data Sovereignty wichtig ist
  5. Prompt Engineering Potential in beide Richtungen – Llama’s False Negatives UND Claude’s False Positives zeigen konkrete Verbesserungs-Ansätze
  6. GPU Offloading ist DER kritische Parameter – Auto-Detection kann konservativ sein, explizites Setzen auf maximale Layers brachte 140% Performance-Gewinn!

Data Sovereignty erreicht die nächste Stufe – von self-hosted LLMs auf Cloud-Infrastruktur (Posts 1-8) zu komplett on-premise. Schneller als Cloud für typische Jobs, $0 Cost, immer verfügbar ohne Capacity-Probleme oder Quota-Management, und jetzt auch ohne Cloud Provider für die Daten selbst.

Wichtige Einschränkung: Dieser Post fokussiert sich auf Inference Performance. Die überraschend gute Performance wirft aber die Frage auf: Wie sieht’s mit Training aus? Könnte LoRA Fine-Tuning aus Post 5 auch lokal auf Mac Studio laufen? Das schauen wir uns in Post 9 an.

Im nächsten Post: Multi-LoRA A/B Testing - Adapter-Iteration basierend auf Evaluation-Feedback. Wie verbessern wir die Performance durch gezieltes Re-Training mit problematischen Patterns?

Ausblick: Für Production Deployment (Argo Workflows, Monitoring, CI/CD) planen wir eine separate Blog-Serie, da diese Themen generisch für alle ML-Pipelines gelten, nicht nur für Self-Hosted LLMs.