
Alisa v Zadzerkalli (ukrainisch) – Alice im Spiegelreich. Die Welt auf der
anderen Seite des Spiegels, in die man absichtlich geht und in der alles
gespiegelt, verkehrt und falsch ist.
«Ніколи не вгадаєш, ким станеш за хвилину.»
„Du kannst nie erraten, wer du in einer Minute sein wirst.“ – Alice, in
Аліса в Країні Див, übers. Valentyn Korniienko, hrsg. Ivan Malkovych, S. 53.
Ein Discord-Bot, geschrieben in C++.
Fähigkeiten
Slash-Befehle
- /ping – Roundtrip-Latenz zum Gateway
- /leaderboard – die Platzierungen des Clube de Programação (UFFS), aus der
vjudge-Gruppe des Clubs gescrapt und nach gelösten Aufgaben sortiert
Konversation
Erwähne sie oder sage „alisa“ oder „obliterator“ in einer Nachricht, und sie
antwortet. Die Antwort wird nicht lokal erzeugt. Alisa stellt den Kontext
zusammen, und Providence übernimmt das Denken.
Was sie dem Modell bei jeder Nachricht vorlegt:
- jedes Clubmitglied, in Leaderboard-Reihenfolge, mit Handle, Anzahl gelöster
Aufgaben und letzter Aktivität - die vollständige Liste der Aufgaben, die jedes Mitglied gelöst hat, pro Judge
- die zehn am häufigsten im gesamten Club gelösten Aufgaben
Dieser Kontext ermöglicht es ihr, Fragen zu beantworten, für die niemand einen
Befehl geschrieben hat. Wer in den Top Drei ist, welche Aufgaben sie gemeinsam
haben, wer verstummt ist. Das Modell liefert die Schlussfolgerung, der Scrape
liefert die Fakten.
Clubdaten
Der Mitgliedsstatus wird beim Start von vjudge durch einen begrenzten Pool von
acht Workern abgerufen, wobei jeder eine Verbindung für seinen Anteil an der
Gruppe hält. Jedes Mitglied kostet zwei Anfragen: die Profilseite für Anzahl
und Rang sowie den Endpunkt für Lösungsdetails für die Aufgabenliste.
Aufbau
- main.cpp – Einstiegspunkt
- src/commands/ – Slash-Befehle und der Dispatcher
- src/members/ – Club-Roster, Profil- und Lösungslisten-Scraping
- src/parser/ – HTML-Abfragen über lexbor
- src/network/ – HTTP mit Verbindungswiederverwendung
- src/speech/ – die Providence-Verbindung und der Prompt-Aufbau
- src/onmessage/, src/onready/ – Gateway-Ereignisbehandler
- src/embeds/ – das Haus-Embed
- src/config/ – Cluster-Einrichtung und gemeinsamer Bot-Zustand
Wie eine Antwort entsteht
Der Nachrichten-Handler wacht bei jeder Nachricht in jedem Kanal auf, den der
Bot sehen kann. Er verwirft Bots, verwirft alles, was sie nicht per Ping oder
durch die Wörter „alisa“ oder „obliterator“ erwähnt, und verwirft derzeit auch
jeden Autor außer einem – eine ID, die in src/onmessage fest verdrahtet ist.
Was übrig bleibt, erhält sofort ein Embed mit dem Text „Thinking…“, das
gepostet wird, bevor das Modell überhaupt gefragt wird, damit der Kanal sieht,
dass sie die Frage annimmt, selbst wenn die Antwort langsam kommt.
Die Antwort selbst ist ein POST an Providence unter http://127.0.0.1:8931 auf
/speech/deepthink/, das die Nachricht, den gesamten Clubkontext und den
Discord-Benutzernamen als Identität des Aufrufers überträgt. Es wartet bis zu
200 Sekunden. Die Antwort wird auf 1990 Bytes an einer UTF-8-Zeichengrenze
gekürzt, sodass ein Schnitt nie mitten in ein Codepoint fällt, und dann wird
das Platzhalter-Embed an Ort und Stelle bearbeitet. Ein Timeout, eine
Ablehnung oder ein nicht parsebarer Text enden alle als Text im selben Embed
statt in Stille.
Providence ist ein separater Dienst und befindet sich nicht in diesem
Repository. Wenn es nicht auf diesem Port läuft, startet der Bot trotzdem,
beantwortet weiterhin Slash-Befehle und scrapt weiterhin den Club – er hört
nur auf zu denken.
Was Providence hinzufügt
Alisa sendet „light true“, den kostengünstigen Pfad: einen Reasoning-Knoten und
keine Verzweigung. Wird dieses Flag entfernt, führt derselbe Endpunkt stattdessen
einen begrenzten Gedankenbaum aus – Tiefe zwei, mindestens zwei beschriftete
Zweige pro Knoten, jeder bewertet nach Erfolgswahrscheinlichkeit und danach,
wie viel Potenzial er hinzufügt oder zerstört, und jeder Knoten wird von einem
nativen Denker erzeugt, der als Unterprozess gestartet wird. Diese Maschinerie
liegt bei jeder Nachricht, die sie sendet, ungenutzt herum.
Sie entscheidet auch selbst, ob die Frage mehr als nur Reden erfordert. Wenn ja,
ordnet ein Klassifikator die Nachricht einem Befehl und seinem Argument zu,
führt ihn aus und fügt das Ergebnis in die endgültige Antwort ein. Was derzeit
auf dieser Liste steht:
- Plotten: eine 2D-Kurve oder eine 3D-Oberfläche aus einer Funktion, die du in
Worten beschreibst - Algebra: vereinfachen, erweitern, faktorisieren, nach einer Variablen lösen
- Analysis: Ableitungen, bestimmte und unbestimmte Integrale, Grenzwerte
- Matrizen: Determinante, Inverse, Eigenwerte
- Rendern beliebiger Ausdrücke als LaTeX
- das UFFS-SIGAA-Portal: aktuelle Disziplinen, Stundenplan, anstehende Aufgaben
- das UFFS-Restaurant: welche Mahlzeiten zur Reservierung offen sind und wie
vergangene liefen, gesteuert über einen echten Headless-Browser mit eigenen
Anmeldedaten
Jede dieser Antworten enthält neben dem Prosa-Text strukturierte Felder. Ein
Plot oder ein LaTeX-Render kommt als Base64-PNG unter „image“ zurück, ein
Portal-Read als JSON unter „data“, und der eigene Kommentar des Modells steht
daneben unter „response“. Alisa liest „response“ und verwirft den Rest, sodass
eine Frage, die ein Diagramm erzeugt, heute als Satz über ein Diagramm bei
Discord ankommt, das niemand sehen kann. Das Senden des Bildes als Anhang ist
das offensichtliche Nächste, das dieser Bot lernen sollte.
Der Zugriff erfolgt pro Aufrufer, nicht pro Bot. Sie identifiziert sich als
„discord“ und mit dem Benutzernamen des Autors, und Providence schlägt dieses
Paar nach und lehnt jeden ab, den es nicht kennt – das ist die Ablehnung, die
sie wörtlich ausgibt. Ein Clubmitglied hinzuzufügen bedeutet, es dort
hinzuzufügen, nicht hier.
Erstellen
Benötigt werden ein C++20-Compiler, CMake 3.16 oder neuer und drei Bibliotheken:
DPP für das Gateway, cpr für HTTP, lexbor für HTML. Auf Arch installiert das
Makefile die fehlenden über yay oder paru. Anderswo installiere sie zuerst
selbst.
make deps DPP, cpr und lexbor holen, falls nicht vorhanden
make konfigurieren und in build/ bauen
make run .env laden, dann die Binärdatei ausführen
make rebuild build/ löschen und neu beginnen
Zwei Dinge am Build sind beabsichtigt. Der Standard-Build-Typ ist
RelWithDebInfo, und parallele Compile-Jobs sind auf zwei begrenzt. DPPs Header
sind template-lastig genug, dass ein unoptimierter Build mehrere Gigabyte pro
Compiler-Prozess kostet, und ein Prozess pro Kern bringt die Maschine damit
zum Absturz. Gib mehr, wenn du den Speicher hast: make JOBS=8.
Quellen werden mit CONFIGURE_DEPENDS geglobbt, sodass eine neue Datei unter
src/ beim nächsten Build erkannt wird, ohne CMakeLists anzufassen.
Konfiguration
Der Bot liest DISCORD_TOKEN aus der Umgebung und sonst nichts. Lege es in .env
im Repository-Stammverzeichnis ab, und „make run“ exportiert es für dich, oder
exportiere es selbst und führe build/alisa-v-zadzerkalli_core direkt aus. Sie
verbindet sich mit den Standard-Intents plus Nachrichteninhalt, was ein
privilegierter Intent ist – aktiviere ihn also für die Anwendung im
Discord-Entwicklerportal, sonst sieht der Nachrichten-Handler nur leere
Zeichenketten.
Providence-Schlüssel liegen daneben in .env für den Dienst am anderen Ende des
Sockets. Diese Binärdatei liest sie nie.
