19 KiB
Projektplan — Setup phy-srv-gpu01 (LLM-Server mit SMB-Wissensbasis)
Date: 2026-07-10 (Stand-Update: 2026-09-03)
Status: In Umsetzung — Server geliefert, Basis-Setup + GPU-Treiber fertig
Basiert auf: 20260706-hardware-assessment.md, 20260706-software-assessment.md, 20260707-deep-dive.md
Stand 2026-09-03 (Kurzfassung — Details in den jeweiligen Abschnitten)
Erledigt: Server geliefert und im Rack; Basis-Setup (Ubuntu 24.04.4, Nutzer,
Netz, RAID/Filesystem — s. SETUP.md im Repo-Root); GPU-Treiber via Ansible-Rolle
nvidia_gpu (595er-Branch, open Kernel-Module — Blackwell läuft nicht mit den
proprietären Modulen, s. manuals/20260714-nvidia-driver-install.md); Docker
installiert. Share-Analyse gelaufen (§2.1).
Als Nächstes: CIFS-Mounts + Container-Stack (Rollen cifs_mounts, llm_stack)
— entspricht Phasen 3–5 in §3.
Kritischer offener Punkt: Der Bestand ist rund 12× größer als die in §1 gesetzte Schwelle. Ohne Eingrenzung des Korpus (Kundengespräch) ist Phase 5 nicht sinnvoll umsetzbar — s. §2.1 und §2.6.
0. Rahmenbedingungen (fixiert)
| Punkt | Entscheidung |
|---|---|
| Hardware | HPE DL380 Gen12, 2× Xeon 6714P, 128 GB RAM, RTX PRO 6000 96 GB, 2× 960 GB NVMe — s. HW.md |
| Betrieb | Bare Metal, keine Virtualisierung des LLM-Stacks |
| Nutzer | ~25, gemischt (technisch versiert + Nicht-Techniker) |
| Auth | AD/LDAP (Details Service-Account/Basis-DN als Pre-Work klären) |
| Berechtigungen | Einfach: alle Nutzer sehen den gesamten indizierten Bestand (Kunde bestätigt; Shares ohne HR-/Personal-Inhalte halten) |
| Sprache | Dokumente & Nutzer überwiegend Deutsch → Modell- und Embedding-Wahl daran ausrichten |
| Inference | vLLM mit fester GPU-Auslastung (kein Ollama als Basis) |
| Wissensbasis | SMB-Shares (einige TB, PDF/Office), Sync ist die Kernanforderung |
| Später | Jira-Anbindung u. a. Workloads; dafür ggf. MIG |
| Vorgehen | Setup vollständig über Ansible (dieses Repo), PoC vorab: nein — reine Planung |
1. Produktentscheidung: Open WebUI statt Onyx
Empfehlung: Open WebUI (bestätigt und verschärft die Empfehlung aus dem Deep Dive §4.7). Ausschlaggebend, Stand 2026-07-10 verifiziert:
- Onyx' File-Connector ist reiner manueller Upload — kein Verzeichnis-Watching,
kein periodischer Re-Sync eines gemounteten Shares
(Doku). Die
Kernanforderung „Shares synchron halten" hieße bei Onyx: Eigenbau gegen
deren API. Open WebUI hat dafür das offizielle Sync-Tool
oikb(inkrementell, Löschungen, Cron-fähig — Deep Dive §4.3). - Onyx: SSO (OIDC/SAML), User Groups, RBAC, Permission-Sync = Enterprise Edition (kostenpflichtig) (Doku). Open WebUI: LDAP/AD-Anbindung und Gruppen sind frei.
- Onyx bringt einen zweiten schweren Stack mit (Vespa-Index, Postgres, Worker) — auf 128 GB RAM neben vLLM spürbar; widerspricht „it just works".
- Bedienung: ein UI im ChatGPT-Stil, vorkonfigurierte Assistenten mit fester Knowledge Base → passt für den gemischten Nutzerkreis.
Wann die Entscheidung zu revidieren ist (Trigger, nach der Share-Analyse §2.1):
- Der relevante Bestand liegt deutlich über ~10⁵ Dokumenten und lässt sich nicht sinnvoll filtern → Suchqualität/Skalierung von Open WebUI prüfen, Onyx (mit Eigenbau-Sync) oder Eigenbau-Pipeline (Deep Dive §4.5) neu bewerten.
- Datei-genaue NTFS-ACLs werden doch Anforderung → Neubewertung (Deep Dive §4.4/4.5).
Status 2026-09-03: Trigger 1 ist eingetreten (1,26 Mio. Office-Dateien, §2.1). Die Produktentscheidung bleibt dennoch bei Open WebUI — aber nur unter der Bedingung, dass der Korpus auf einen kuratierten Teilbestand eingegrenzt wird (§2.6). Ein ungefilterter Vollindex über 1,26 Mio. Dokumente ist mit Open WebUI nicht sinnvoll zu betreiben (und liefert auch inhaltlich schlechte Antworten — RAG über einen kompletten, ungeordneten Fileserver retourniert überwiegend Rauschen).
Jira später: für Indizierung von Jira-Inhalten hat Onyx zwar native Konnektoren, Open WebUI deckt das aber über Tools/MCP (Atlassian-MCP) bzw. API-Workloads direkt gegen vLLM ab — kein Entscheidungskriterium für heute.
2. Phase 0 — Pre-Work (jetzt, ohne Server)
2.1 Share-Analyse (wichtigster Punkt — ja, unbedingt vorab)
Read-only-Skript auf einer beliebigen Maschine mit Share-Zugriff (kein GPU-Server nötig). Zu erheben:
- Volumen & Dateianzahl pro Share und Dateityp (pdf/docx/xlsx/…)
- Anteil gescannter PDFs (Stichprobe: PDFs ohne Textlayer) → OCR-Bedarf
- Duplikate/Altversionen („Kopie von …", Versionsordner) → Filterregeln
- Änderungsrate (mtime-Verteilung) → Sync-Frequenz
- Anteil nicht extrahierbarer Formate (CAD, Bilder, Archive) → Erwartungsmanagement
- Sonderzeichen/Pfadlängen, Encoding (Umlaute!)
Ergebnis bestimmt: Korpus-Umfang (→ §1-Trigger), OCR-Pipeline ja/nein, Index-Größe (→ Storage-Check §2.3), Erst-Indexierungsdauer.
Ergebnis (Lauf 2026-09-03, Skript scripts/share-analysis.ps1 auf D: des
Fileservers Z-FILESERVER; Zahlen ggü. dem Erstlauf 2026-07-14 leicht gewachsen):
| Kennzahl | Wert | Konsequenz |
|---|---|---|
| Gesamt | 3.338.643 Dateien, 2.231 GB | Scan lief über D: gesamt, nicht je Share → Obergrenze, enthält evtl. nicht freigegebene Daten |
office (extrahierbar) |
1.271.467 Dateien, 591 GB | 12× über der §1-Schwelle → Eingrenzung zwingend (§2.6) |
other (unklassifiziert) |
1.576.747 Dateien, 919 GB | größter Block, noch unidentifiziert → D-file-types.csv auswerten |
| Bilder / CAD / Archive / Medien | 403k / 60k / 12,6k / 6,2k Dateien | nicht extrahierbar → Erwartungsmanagement |
| PDFs | 935.186, davon ~22 % ohne Textlayer (Stichprobe 200) | ≈ 200.000 Scan-PDFs → OCR; eigener Zeit-/GPU-Aufwand, konkurriert mit vLLM |
| Änderungsrate | 94 % älter als 1 Jahr; nur ~158k in den letzten 365 Tagen | Sync-Frequenz unkritisch; Alter ≠ Irrelevanz (Datenblätter, Normen) → Filter primär ordner-/inhaltsbasiert, Aktualität nur sekundär |
| Duplikat-/Altversions-Muster | 33.378 Dateien | Filterregeln |
| Pfade > 240 Zeichen | 25.866 | Extraktions-Toolchain gezielt testen |
| Nicht-ASCII-Dateinamen | 126.899 | UTF-8 durchgängig (CIFS-Mount-Optionen → Extraktion → Index) |
Bug im Erstlauf: Beim Lauf über D: wurden keine CSVs geschrieben
(Export-Csv scheiterte an D: im Dateinamen). Behoben am 2026-09-03; für die
Ordner-Aufschlüsselung neu laufen lassen mit:
.\share-analysis.ps1 -Paths "D:" -OutDir .\file-analysis -FolderDepth 2
-FolderDepth 2 liefert Größe/Anzahl je Abteilungen\<Share> — genau die
Granularität der Freigaben (s. §2.7) und die Grundlage für die Include-/
Exclude-Liste. Ebenfalls auszuwerten: D-file-types.csv zur Auflösung der
other-Kategorie (1,58 Mio. Dateien, größter unidentifizierter Block).
2.2 Mit dem Kunden zu klären (Checkliste) — Stand 2026-09-03
- AD/LDAP: AD-Gruppe
llm_userswird angelegt. Offen: Bind-Service-Account und Basis-DN (werden für die LDAP-Konfiguration in Open WebUI gebraucht) - SMB-Service-Account read-only wird separat angelegt (kein Nutzer-Account)
- Welche Shares/Unterordner in den Index? — offen, wird besprochen; wichtigster Punkt, s. §2.1/§2.6
- DNS-Name
chat.phytron.local(vorerst); kein TLS/keine lokalen Zertifikate zu Beginn → reines HTTP im LAN. Hinweis: AD-Passwörter gehen damit im Klartext über das Netz; für später ein internes CA-Zertifikat einplanen (Reverse Proxy ist vorbereitet, nur Zertifikat fehlt) - Internetzugang: unbeschränkt, keine Einschränkung nötig
- Protokollierung/Datenschutz: noch zu besprechen (Chat-Logs = Verhaltensdaten; Betriebsrat/DSGVO) — vor dem Rollout klären, nicht vor der technischen Umsetzung
- Betrieb/Wartung/Updates: wir (Softbox)
- „Andere Workloads": Jira vorerst nicht relevant → MIG bleibt aus, die volle GPU geht an den LLM-Stack
2.3 Storage-Check — ✅ erledigt, unkritisch
Ist-Stand auf dem Server: 876 GB nutzbar (/, LVM), davon 818 GB frei.
Gegenrechnung mit §2.1: selbst ein Vollindex des office-Bestands
(1,26 Mio. Dokumente → grob 150–250 GB inkl. extrahiertem Text, Embeddings und
Index-Overhead) plus Modelle (~100 GB) passt. Strategie bleibt: kein lokaler
Spiegel der Shares, nur Index. Keine zusätzlichen NVMe nötig.
Der begrenzende Faktor ist damit nicht der Plattenplatz, sondern Retrieval-Qualität und Indexgröße (§2.6).
2.4 Ansible — Stand 2026-09-03
run.yml: Play fürphy_srv_gpu01(security, docker, nvidia_gpu, compose)nvidia_gpu— Treiber (595 open), Container Toolkit; läuft auf dem Server- LLM-Stack als Compose-Templates statt eigener Rolle: über
ironicbadger.docker_compose_generator(auf 2.0.1 gepinnt), analog zum Homelab-Repo. Fragmente unteransible/services/phy-srv-gpu01/:01-vllm,02-embeddings,03-openwebui(+ pgvector),99-network. Die Rolle schreibt nur~/docker/compose.yaml; das Starten bleibt ein bewusster manueller Schritt. cifs_mounts— ro-Mounts, Credentials ausgroup_vars/secrets.yml(erst sinnvoll, wenn die Freigaben-Auswahl steht, §2.6/§2.7)- oikb-Sync (Share → Knowledge Base), ebenfalls nach der Auswahl
- Reverse Proxy + TLS — bewusst zurückgestellt (§2.2), Stack
04-proxy group_vars/phy_srv_gpu01.yml: Overrides (Modell, VRAM-Quoten, LDAP, Compose-Pfade). Offen: echte LDAP-DNs und drei Vault-Secrets (vault_owui_secret_key,vault_owui_db_password,vault_ldap_bind_password)
Warum Compose-Templates und keine eigene llm_stack-Rolle: gleiche Konvention
wie im Homelab-Repo (ein Ordner je Stack, NN--Präfix bestimmt die Reihenfolge),
dadurch weniger Eigenbau und für den Wiedereinstieg vertraut.
2.5 Modell-Shortlist — Entscheidung 2026-09-03
Startmodell: Qwen3-32B FP8. Begründung: ~35 GB VRAM, damit reichlich Reserve für KV-Cache (~25 parallele Nutzer) und das Embedding-Modell daneben; gutes Deutsch; hoher Durchsatz. Alternative bei Qualitätsbedarf: gpt-oss-120b (MoE, ~60–65 GB) — weniger Parallelität, engerer Fit. Embeddings: bge-m3 / multilingual-e5 (mehrsprachig, zwingend für Deutsch).
Das ist der Startwert als Rollen-Variable, keine endgültige Festlegung: Die finale Wahl fällt gegen das Eval-Set (s. u.) und nach dem vLLM-Smoke-Test.
⚠️ Offener technischer Punkt: Die offiziellen vLLM-Docker-Images unterstützen
SM120 (Blackwell Workstation/Server) laut aktueller Quellenlage nicht
zuverlässig out of the box; auf RTX-PRO-6000-Systemen werden verbreitet
Nightly- oder Community-Builds eingesetzt
(vLLM-Forum,
rtx6kpro).
Vor dem Bau der Rolle llm_stack daher ein Container manuell auf dem Server
testen und das funktionierende Image pinnen — dieselbe Fehlerklasse wie beim
Treiber (proprietäre vs. open Kernel-Module).
Kleines deutsches Eval-Set (20–30 Fragen mit erwarteten Antworten aus dem Bestand) mit dem Kunden sammeln — das ist später das Abnahmekriterium.
2.6 Korpus eingrenzen (neu, wichtigster offener Punkt)
Die Share-Analyse (§2.1) hat 1,26 Mio. potenziell extrahierbare Dokumente ergeben. „Alles indizieren" ist weder technisch sinnvoll noch inhaltlich wünschenswert. Vorschlag für das Kundengespräch:
- Ordner statt Alter als Filter. Aus
D-toplevel-folders.csvgemeinsam mit dem Kunden die Ordner markieren, die tatsächlich Wissensbasis sind (Doku, Normen, Datenblätter, Handbücher, Projektdoku) — Rest bleibt außen vor. Reiner Aktualitätsfilter wäre falsch: Datenblätter und Normen sind über Jahre gültig. - Ausschlusslisten für Duplikate/Altversionen (33k Treffer), Archiv- und Backup-Ordner, nicht extrahierbare Formate (CAD, Bilder, Medien).
- Zielgröße nennen. Als Orientierung: eine gut funktionierende Wissensbasis liegt eher im Bereich 10.000–100.000 Dokumente. Das ist kein hartes Limit, aber der Bereich, in dem Retrieval-Qualität und Indexierungsdauer beherrschbar bleiben.
- Iterativ starten. Phase 5 zuerst mit einem gut abgegrenzten Share/Ordner, Qualität am Eval-Set (§2.5) messen, dann erweitern. Das erspart einen tagelangen Fehlversuch über den Gesamtbestand.
Erwartungsmanagement gegenüber dem Kunden: Die ursprüngliche Anforderung lautete sinngemäß „unsere Dokumente auslesen". Realistisch ist „ein kuratierter Teil unserer Dokumente, dafür mit guten Antworten". Das früh sagen — nicht erst, wenn der Vollindex schlechte Treffer liefert.
2.7 Freigaben-Inventar (Stand 2026-09-03)
scripts/list-shares.ps1 auf Z-FILESERVER: 30 Freigaben, alle unterhalb D:,
kein DFS. Vorschlag als Gesprächsgrundlage — die Zuordnung der Kürzel muss der
Kunde bestätigen, ebenso die endgültige Auswahl:
| Freigabe | Pfad | Vorschlag | Begründung |
|---|---|---|---|
| QM | D:\Abteilungen\QM |
rein | Qualitätsmanagement — Normen, Prüfvorschriften: Kern der Wissensbasis |
| Arbeitssicherheit | D:\Arbeitssicherheit |
rein | Vorschriften, Betriebsanweisungen |
| Competence Center | D:\Abteilungen\Competence Center |
rein | Name deutet auf kuratiertes Wissen |
| EDV | D:\Abteilungen\EDV |
rein | IT-Doku |
| Produktion | D:\Produktion |
prüfen | vermutlich groß; ggf. nur Unterordner mit Doku |
| Projekte | D:\Projekte |
prüfen | vermutlich der größte Block; nur mit Unterordner-Filter sinnvoll |
| Lagerlogistik, Marketing, Kalkulationen, Controlling, Immobilie | div. | prüfen | fachlich abhängig, eher zweite Welle |
| AA, AZ, BU, EE, EF, EK, ME, MF, MM, PL, SG, VT | D:\Abteilungen\* |
klären | Abteilungskürzel — Bedeutung und Inhalt vom Kunden bestätigen lassen |
| Zeichnungen | D:\Abteilungen\Zeichnungen |
raus | CAD/Zeichnungen — nicht extrahierbar (s. cad/image in §2.1) |
| Datenbank | D:\Datenbank |
raus | Datenbank-Dateien, kein Fließtext |
| Tempwork | D:\Tempwork |
raus | temporär, per Definition kein Wissensbestand |
| Benutzer | D:\Benutzer |
raus | persönliche Ablagen — Datenschutz, kein geteiltes Wissen |
| Personal | D:\Abteilungen\Personal |
raus | HR — explizit ausgeschlossen (§0: „alle sehen alles" gilt nur ohne Personaldaten) |
| GF | D:\Abteilungen\GF |
raus | Geschäftsführung — vertraulich |
| BR | D:\Abteilungen\BR |
raus (klären) | falls Betriebsrat: besonders schutzwürdig, auf keinen Fall indizieren |
⚠️ Wichtig: Weil alle Nutzer alles sehen (§0), ist jede indizierte Freigabe für
alle 25 Nutzer lesbar — unabhängig von den NTFS-Rechten auf dem Fileserver. Die
Ausschlüsse oben sind deshalb keine Kosmetik, sondern die einzige Zugriffskontrolle.
list-shares.ps1 gibt die NTFS-Gruppen je Freigabe mit aus: Alles, was heute nur
einem eingeschränkten Personenkreis offensteht, gehört nicht in den Index.
3. Phasen ab Server-Lieferung
| Phase | Inhalt | Ergebnis/Abnahme |
|---|---|---|
| 1. Basis (Woche 1) | Rack/Strom (600-W-GPU!), iLO, Firmware, RAID, Ubuntu 24.04 LTS, Eintrag in Ansible-Basis-Setup (Security, Pakete, Nutzer) | just run phy_srv_gpu01 läuft grün |
| 2. GPU-Stack (Woche 1–2) | Rolle nvidia_gpu: Treiber, Container Toolkit, DCGM; Burn-in unter Dauerlast (SM120-Risiken, Deep Dive §1.6); MIG erst mal aus |
nvidia-smi ok, 48 h-Lasttest ohne Reset |
| 3. Inference (Woche 2) | vLLM-Container (NVIDIA-Build) mit gewähltem Modell, feste VRAM-Quote, Embedding-Server daneben; Benchmark mit Eval-Set | deutsche Antworten ok, Ziel-Parallelität erreicht |
| 4. UI + Auth (Woche 2–3) | Open WebUI + pgvector, LDAP-Login, Reverse Proxy + TLS, vorkonfigurierter „Phytron-Assistent" | Login mit AD-Konto, Chat läuft |
| 5. Wissensbasis (Woche 3–5) | CIFS-Mounts (ro), Extraktion inkl. OCR-Engine (Tika/Docling), oikb-Sync erst auf einen Teilbestand, Qualität prüfen, dann Vollindex (Dauer aus §2.1 abschätzen) | Fragen aus dem Eval-Set werden mit korrekten Quellen beantwortet |
| 6. Pilot → Rollout (Woche 5–7) | 3–5 Pilotnutzer (gemischt), Feedback, dann alle 25; Onboarding-Einseiter (was kann es, was nicht — CAD/Scans!) | Abnahme durch Kunden |
| 7. Betrieb | Monitoring (GPU/DCGM, Dienste), Backup (Konfig + DBs — Modelle nicht), Update-Runbook manuals/, Doku im README |
Runbooks vorhanden |
| später | Jira & weitere Workloads; erst dann MIG-Layout festlegen (bis 4 Instanzen) statt jetzt raten | — |
4. Risiken
| Risiko | Umgang |
|---|---|
| ✅ erledigt — 876 GB nutzbar, reicht (§2.3) | |
| Korpus 12× über der Planungsschwelle (§2.1) | Eingrenzung auf kuratierten Teilbestand (§2.6); ohne Kundenentscheid keine Phase 5 |
| ~166.000 Scan-PDFs → OCR-Aufwand & -Qualität | eigener Arbeitsblock, GPU-Konkurrenz zu vLLM einplanen; Erwartungen dämpfen |
✅ erledigt — Treiber 595 open läuft (proprietäre Module scheitern an RmInitAdapter) |
|
| Kein TLS zu Beginn (§2.2) | AD-Passwörter im Klartext im LAN; internes CA-Zertifikat nachrüsten, Reverse Proxy vorbereiten |
| Software-Stand veraltet bis Lieferung | Versionen erst bei Installation pinnen; Wiedereinstiegs-Checkliste |
| Erst-Indexierung dauert Tage | Teilbestand zuerst; Sync nachts; Dauer vorab abschätzen |
| RAM-Konkurrenz Extraktion/OCR vs. vLLM | vLLM hat feste VRAM-Quote; Indexer-Jobs drosseln (nice/cgroups); 128 GB reichen für OWUI-Stack |
| Datenschutz/Betriebsrat bei Chat-Logs | Früh klären (§2.2), Logging-Policy dokumentieren |
| Kein HA — ein Server | Erwartung managen: Wartungsfenster = Dienst weg; Backup-Restore-Runbook |
5. Wiedereinstiegs-Checkliste (wenn der Server da ist)
- Dieses Dokument + Deep Dive lesen; offene Punkte aus §2.2 abhaken
- Ergebnis der Share-Analyse vorliegen? → §2.1
- Neu sichten & dann erst pinnen: vLLM-Version (RTX-PRO-6000-/SM120-Support), Open WebUI + oikb Release Notes, Modell-Shortlist §2.5 — NVIDIA-Treiber ✅ (595-open)
- Storage-Entscheidung §2.3 → unkritisch, nichts nachzubestellen
- Dann Phasenplan §3 von oben abarbeiten; jede Phase = Ansible-Commit + ggf.
Runbook unter
manuals/
6. Bewusst offen gelassen (kein Jetzt-Entscheid nötig)
- Exaktes Modell & Quantisierung, vLLM-Flags, MIG-Layout, OCR-Engine-Wahl, Monitoring-Stack-Details, Reverse-Proxy-Produkt — alles bei Umsetzung mit aktuellem Stand entscheiden; Rahmen steht oben.