Lucas AI aufbauen: Ein Portfolio in ein Produkt verwandeln

Passwort vergessen

22. April 20267 min gelesen

Lucas AI aufbauen: Ein Portfolio in ein Produkt verwandeln

Begrenzte LLM-UX: Zwei-Schritt-Inferenz, SSE-Streaming, strukturierte Verankerung und die Produktgrenzen, die einen Portfolio-Chat ehrlich halten.

ProduktKIFrontend

Die meisten Portfolios entwickeln sich nicht weiter. Ich wollte, dass dieses Portfolio sich wie ein Produkt verhält: i18n-first, gemeinsame Benutzeroberfläche in einem Monorepo und eine Lucas AI-Schicht, die in der ersten Person über meine Arbeit antwortet – nur aus strukturiertem Kontext, der in die Bereitstellung eingebacken ist. Dieser Beitrag ist für Ingenieure, die das Systembild wollen: Inferenzform, Streaming, Verankerung und explizite Nicht-Ziele – kein Rundgang durch die Dateistruktur oder wie man einen Fork lokal ausführt.

Was es löst

Statische Seiten sind schlecht bei Follow-ups. Wenn Ihre Stärke im Urteil liegt – Umfang, Kompromisse, wie Sie unter Zwang geliefert haben –, reicht ein PDF und ein Kontaktformular nicht aus, um Neugier zu befriedigen. Lucas AI ist ein dediziertes Ziel (/[locale]/ai): Fragen Sie nach Erfahrungen, der Website oder der Funktion selbst, ohne zu behaupten, ich sei in Echtzeit am anderen Ende der Leitung.

Hocharchitektur

Der Browser besitzt die Transkript-Benutzeroberfläche; der Server besitzt Richtlinie und Aufwand. Jede Sendung ist ein POST /api/chat mit { message, locale } – keine Anhänge, keine Werkzeugaufrufe, keine versteckten Felder.

Der Handler baut ein System, leitet an Groq's OpenAI-kompatibles /v1/chat/completions weiter und proxys den Upstream-Stream als Server-Sent Events (SSE), damit Token inkrementell gerendert werden, ohne die vollständige Fertigstellung im Speicher am Rand zu puffern. Dies ist dasselbe Muster, das Sie hinter jeder schnellen Inferenz-API verwenden würden: Behandeln Sie die Route als dünnen Adapter, halten Sie das Drahtformat für den Client stabil.

Die Verankerung lebt im Anwendungscode: ein typisierter Karriereobjekt wird einmal in eine CONTEXT-Zeichenfolge formatiert und in die Systemnachricht injiziert. Es gibt keine Vektordatenbank und keinen Abrufschritt zur Anfragezeit – das Modell sieht nur, was Sie serialisiert haben, als Sie die Eingabeaufforderung erstellt haben. Dies ist ein Kapazitätshandel (Sie können nicht aus beliebigen Dokumenten antworten) im Austausch für vorhersehbare Latenz, Kosten und Prüfoberfläche.

Modelle und Aufrufe

  • Hauptantwort: Standard llama-3.3-70b-versatile auf Groq (Überschreiben von GROQ_MODEL). Streaming bleibt an; die Route erlaubt bis zu 60s der Generierung – genug für eine sorgfältige Antwort, ohne den Rand in einen unbegrenzten Arbeiter zu verwandeln.
  • Vorflug-Klassifikator: llama-3.1-8b-instant (konfigurierbar als CLASSIFIER_MODEL). Es ist ein getrennter, nicht-streamender Aufruf mit max_tokens: 5, temperature: 0 und einer minimalen Systemaufforderung, die die Entscheidung auf ein einzelnes Token reduziert: CAREER oder OFF_TOPIC.

Wenn das Urteil OFF_TOPIC ist, ruft die API nie das große Modell auf. Es streamt eine feste, lokalisierte Ablehnung als SSE, damit der Client-Codepfad einem "echten" Abschluss entspricht – keine spezielle UI-Zweig für das Kurzschließen. Wenn der Klassifikator fehlerhaft oder zeitlich abgelaufen ist, fällt der Handler offen und führt das Hauptmodell trotzdem aus: ein billiges Gate darf nicht zu einem einzigen Fehlerpunkt für legitimen Verkehr werden.

Das Gate kann am Host (Server-Umgebung) deaktiviert werden, wenn Sie bewusst akzeptieren, dass jede Kurve das große Modell trifft – nützlich, wenn der kleine Endpunkt ungesund ist, wenn Sie den Antwortpfad allein testen oder wenn Produktpolitik sich ändert und Sie vorübergehend das Gating fallen lassen. Dieser Knopf lebt außerhalb der Sicht des Besuchers; es ist ein Operationshebel, kein Funktionsflag in der Benutzeroberfläche.

Ausgabenbudget: Der Assistent max_tokens ist begrenzt (CHAT_MAX_TOKENS, geklemmt 256–8192, Standard 2048). Es koppelt UX ("Antworten sollten enden") mit Einheitswirtschaften auf der Anbieterrechnung.

Was wir an den Server senden (und was wir nicht)

Jede Anfrage trägt:

  • message: der aktuelle Benutzerschritt, getrimmt, mit einer harten Kappe von 2 000 Zeichen (Oberfläche für Missbrauch und Eingabeaufforderung reduzieren).
  • locale: normalisiert auf eine unterstützte Website-Lokalisierung. Die Systemaufforderung endet mit Visitor locale: …, damit das Modell in der Website-Sprache antwortet, nicht in der Sprache, die die Benutzeroberfläche verwendet.

Was wir nicht senden:

  • Keine vorherigen Schritte über die Leitung. Der Backend ist einzelner Schritt pro Anfrage: Systemaufforderung + eine Benutzernachricht. Der Thread, den Sie in der Benutzeroberfläche sehen, wird nicht zum Modell bei jedem Senden wiedergegeben.

Die "Erinnerung" ist also: veröffentlichter CONTEXT + was immer noch in der Client sichtbar ist. Dies ist eine bewusste Grenze: kein serverseitiger Chat-Verlauf, keine geräteübergreifende Synchronisierung, kein Training auf Gespräche.

Wo der Thread lebt

Die Benutzeroberfläche persistiert Nachrichten in sessionStorage (lucas-ai-messages). Aktualisieren Sie im selben Tab hält den Thread; ein neuer Tab oder Gerät startet sauber. Es gibt einen zweiten Schlüssel, lucas-ai-pending, der verwendet wird, wenn wir den Benutzer nach einem Lokalisierungsschalter umleiten (mehr unten).

Wenn GROQ_API_KEY fehlt, gibt die Route immer noch SSE zurück: sie streamt die lokalisierte Konfigurationsfehlerzeichenfolge, damit die Shell ohne Wegwerfen des Layouts degeneriert.

Strukturierte Verankerung (kein RAG)

Der Karriere-Korpus beginnt als typisierte Datensätze – Rollen, Stacks, Initiativen, Metriken, kind (Arbeit vs. Freiwilligenarbeit vs. Bildung vs. persönlich), Zeitbereiche und optionale narrative Felder. Ein Formatter verwandelt dies in einen einen Markdown-ähnlichen Block, der in explizite Begrenzer gewickelt ist, z. B.:

--- CONTEXT (Wahrheitsgrundlage; nicht widersprechen oder darüber hinausgehen) ---

--- Ende des Kontexts ---

Was hineingeht, ist genauso wichtig wie das, was draußen bleibt:

  • Bio, Stärken, Prinzipien, Arbeitsstil – Orientierung ohne Lebenslaufgeräusch.
  • Erfahrung – pro Arbeitgeber: Umfang, Initiativen (was / Wirkung / Beweise), Metriken und optionale context / problem / lösung / Wirkung-Geschichten, wenn Sie möchten, dass das Modell in Ergebnissen spricht, nicht in Schlagwörtern.
  • Dauerzusammenfassung – kalender-deduplizierte Monate für professionelle Arbeit mit Regeln, die Überlappungen oder das Einschmuggeln von Hobbyprojekten in "Erfahrungsjahre" verhindern.
  • Ein selbstbeschreibender "Produkt + Implementierung"-Schnitt – keine Marketing-Kopie, sondern Fakten, die Sie verteidigen möchten: Hosting-Form, i18n-Ansatz, wie Chat aufgerufen wird, Streaming, Klassifikatorverhalten, wo Zustand lebt, Datenschutzhaltung. Der Punkt dieses Schnitts ist Meta-Fragen, die aus demselben Wahrheitsgrundobjekt wie Karrierefragen beantwortet werden – damit "Wie funktioniert diese Funktion?" kein Blankoscheck für das Modell wird, um Dateibäume oder Abhängigkeiten zu erfinden.

Darüber hinaus ist das System ein strenges Gesetz: erste Person, kein Vortäuschen, live auf Slack zu sein, kein Zugriff auf private Systeme, kein Dritter "Lucas sagte…", CONTEXT als einziger faktischer Quelle und keine Fabrikation jenseits dessen, was CONTEXT für Implementierungsdetails angibt.

Dies ist, wie Sie "nicht halluzinieren" von einer Stimmung in prüfbare Reichweite verwandeln: das Modell ist nur so intelligent wie das Bundle, das Sie liefern, und das Bundle ist wie Code versioniert.

Themenklassifikator (was als in-scope gilt)

Die Aufgabe des kleinen Modells besteht nur darin, zu routen, nicht hilfreich zu sein. CAREER wird breit definiert: Hintergrund, Fähigkeiten, gelieferte Arbeit, Produkturteil und legitime Fragen zur Website selbst – Stack, Lokalisierungspipeline, wie der Assistent verkabelt ist – soweit diese Informationen in CONTEXT existieren. OFF_TOPIC fängt alles andere ein (Wetter, Hausaufgaben, irrelevante Trivia).

Die Behandlung von "Meta"-Fragen als in-scope ist eine Produktentscheidung: ein Portfolio-Assistent sollte seine eigenen Randbedingungen erklären, ohne die gesamte Website als Wissensquelle zu öffnen.

Eingabe-Sprache vs. Website-Lokalisierung (clientseitig)

Die Route-Lokalisierung treibt Antwortsprache (via Prompt). Aber Benutzer tippen manchmal in einer anderen Sprache, während sie auf z. B. der englischen Benutzeroberfläche bleiben.

Beim Senden führt der Client franc-min auf der Eingabe aus (minimale Länge ~15 Zeichen). Wenn die erkannte Sprache nicht mit der erwarteten ISO 639-3-Zuordnung der aktuellen Lokalisierung übereinstimmt, posten wir nicht still an die API. Wir zeigen eine Angebotskarte: Schaltflächen zum router.push(/${targetLocale}/ai) für übereinstimmende Lokalisierungen plus "in aktueller Sprache fortsetzen". Wenn sie die Lokalisierung wechseln, speichern wir die ausstehende Nachricht in sessionStorage, navigieren und senden dann automatisch nach dem Mount, damit die Frage mit der richtigen locale im JSON-Body ausgeführt wird.

Dies ist Produktverhalten: Website-Sprache mit der Sprache ausrichten, in der der Benutzer tatsächlich schreibt, anstatt das Modell erraten zu lassen oder Richtlinien zu vermischen.

UX-Platzierung

Lucas AI ist ein Nav-Ziel und ein Heimatabschnitt (Abzeichen, Überschrift, CTA, Beispielaufforderungen) – kein schwebendes Widget über dem Lesefluss. Die Vollseiten-Chat hält das Muster opt-in und vermeidet das "Überraschung-Copilot"-Anti-Muster, bei dem generative Benutzeroberfläche mit dem Rest des Layouts um Aufmerksamkeit kämpft.

Fehler-Modi, die wir uns vorgenommen haben

  • Klassifikator down: zum Hauptmodell fortfahren (offen fallen).
  • Groq 401/403/400: JSON llm_auth an den Client zurückgeben – kein roher Upstream-Body (Vermeidung von Leck oder Modellhinweisen).
  • 5xx / 429: einen lokalisierten generischen Fehler via Mock SSE streamen, wenn angemessen.
  • Leere oder übergroße Nachricht: 400 mit einem stabilen Fehlercode.

Zusammenfassung

Lucas AI ist kein allgemeiner Assistent, der auf eine Marketing-Seite fallen gelassen wird. Es ist ein enges Produkt: ein Körper von Fakten, hinter dem Sie stehen, ein Streaming-Antwortpfad, ein kleines Modell, das nur entscheidet, "in-scope oder nicht", und ein Server, der jeden Schritt absichtlich vergisst. Das Ziel ist vorhersehbares Verhalten – was an den Anbieter gesendet wird, was Sie die Inferenz-API pro Anfrage bezahlen, und was der Besucher als faktisch behandeln darf.

Wenn Sie etwas Ähnliches aufbauen, liegt der Hebel nicht darin, das größte Modell auszuwählen. Es besteht darin, die Systemnachricht und den CONTEXT wie eine Spezifikation zu behandeln – schlicht, faktisch, zeilenprüfbar – anstatt Marketing-Kopie, und in der Architektur zu entscheiden, wann das große Modell überhaupt laufen darf (z. B. nur nach einem On-Topic-Gate).