Problem
Ein Lebenslauf ist statisch; wer ihn gelesen hat, muss den Rest erraten. Ein Sprachmodell für sich sprechen zu lassen, wirft aber drei echte Probleme auf: Es erfindet Erfahrungen, es gibt Dinge preis, die es nicht sollte, und es verbraucht Budget, während niemand hinsieht.
Praktisch die gesamte Entwicklungsarbeit in diesem Projekt beantwortet diese drei Punkte.
Vorgehen
- Backend — FastAPI mit drei Schnittstellen: Profil, JSON-Chat und SSE-Streaming; eine Adapterschicht übernimmt Abbruch, Wiederholung und Ratenbegrenzung
- Frontend — ein natives Custom Element mit Shadow DOM, ohne Laufzeitabhängigkeiten, mit einem Script-Tag und einem Element in jede Seite einbettbar
- Zwei Persönlichkeiten — beruflich und locker, jeweils mit eigener, getrennter Sitzung; ein Wechsel vermischt die Verläufe nicht
- Drei Sprachen — Chinesisch, Englisch, Deutsch, mit sitzungsgetrennter Speicherung pro Tab, anonymen UUIDs und ohne geräteübergreifendes Langzeitgedächtnis
- Sicherheit — XSS-Schutz, sicheres Rendern, strikte CORS-Regeln in der Produktion
- Betrieb — Docker-Image ohne Root-Rechte, dynamischer Port, Health Checks, sauberes Herunterfahren bei SIGTERM
Drei Entscheidungen, die eine Erklärung wert sind
1. Grenzen brechen den Start ab, sie warnen nicht
Die CORS-Konfiguration akzeptiert in der Produktion genau zwei Ursprünge. Ein Platzhalter, ein lokaler Ursprung, ein fehlender oder ein zusätzlicher Eintrag verhindern den Start. Fehlt das freigegebene Profil, startet der Dienst ebenfalls nicht.
Eine solche Grenze als Warnung zu schreiben, ist dasselbe, wie sie nicht zu schreiben — gelbe Zeilen im Log liest niemand.
2. Beobachtbar, aber nicht neugierig
Der Chat-Pfad erzeugt pro Anfrage eine anonyme, strukturierte Kennzahl: freigegebene Metadaten, Latenz, Fehlerklasse und Token-Verbrauch. Aufgezeichnet werden keine Fragen, keine Antworten, kein Verlauf, keine Identität und keine Zugangsdaten. Das Protokollieren von Rohgesprächen ist in der Produktion durch eine Konfigurationsgrenze abgeschaltet, und ein Fehler im Kennzahlencode wird verschluckt, damit er den Chat nie unterbrechen kann.
Um zu wissen, ob das System funktioniert, muss man nicht lesen, was die Leute hineingeschrieben haben.
3. Betrieb ohne laufende Kosten
Eine feste Obergrenze für Ausgabetoken, eine Nebenläufigkeitsgrenze, eine Ratenbegrenzung pro Minute, ein Tageslimit pro IP-Adresse und ein Tageslimit pro Sitzung halten die Kosten gemeinsam unten. Ruhezustand und Kaltstart des kostenlosen Tarifs sind eine bewusst akzeptierte Einschränkung; für die Überwachung kommt keine kostenpflichtige Ressource hinzu.
In Arbeit
Ein selbst gehosteter Inferenzpfad mit llama.cpp und einem quantisierten Qwen3-4B läuft lokal bereits. Derzeit trainiere ich ein kleines Decoder-only-GPT von Grund auf — nicht, um ein allgemeines Modell zu ersetzen, sondern um die gesamte technische Kette einmal zu durchlaufen: vom Training über den quantisierten Export bis zur Auslieferung hinter derselben OpenAI-kompatiblen Schnittstelle.
In der Produktion bleibt die gehostete Schnittstelle die Voreinstellung; kein Experiment schaltet sie automatisch um.