Alisa V Zadzerkalli
C++

Alisa V Zadzerkalli

Alisa v Zadzerkalli - un bot Discord scritto in C++

GitHub|
image

Alisa v Zadzerkalli (ucraino) - Alice Through the Looking-Glass. Il mondo
al di là dello specchio, dove vai apposta e tutto è
riflesso, al contrario e sbagliato.

«Ніколи не вгадаєш, ким станеш за хвилину.»
"Non puoi mai indovinare chi diventerai tra un minuto." - Alice, in
Аліса в Країні Див, trad. Valentyn Korniienko, ed. Ivan Malkovych p. 53.

Un bot Discord scritto in C++.

Funzionalità

Comandi slash

  • /ping - latenza di andata e ritorno verso il gateway
  • /leaderboard - la classifica del Clube de Programação (UFFS), recuperata dal
    gruppo vjudge del club e ordinata per problemi risolti

Conversazione

Menzionala, o scrivi alisa o obliterator in un messaggio, e lei risponde. La
risposta non è generata localmente. Alisa assembla il contesto e Providence
fa il pensiero.

Cosa mette davanti al modello su ogni messaggio:

  • ogni membro del club, in ordine di classifica, con il suo handle, il numero di
    problemi risolti e l'ultima attività
  • l'elenco completo dei problemi risolti da ogni membro, per giudice
  • i dieci problemi risolti più spesso in tutto il club

Questo contesto è ciò che le permette di rispondere a domande per cui nessuno ha
scritto un comando. Chi è nella top tre, quali problemi hanno in comune, chi è
diventato silenzioso. Il modello fornisce il ragionamento, lo scraping fornisce
i fatti.

Dati del club

Lo stato dei membri viene recuperato da vjudge all'avvio tramite un pool
limitato di otto worker, ciascuno con una connessione per la sua parte del
gruppo. Ogni membro costa due richieste: la pagina del profilo per conteggi e
rank, e l'endpoint dei dettagli dei problemi risolti per l'elenco dei problemi.

Struttura

  • main.cpp - punto di ingresso
  • src/commands/ - comandi slash e dispatcher
  • src/members/ - roster del club, scraping di profilo ed elenco problemi
  • src/parser/ - interrogazione HTML su lexbor
  • src/network/ - HTTP con riutilizzo delle connessioni
  • src/speech/ - collegamento a Providence e assemblaggio del prompt
  • src/onmessage/, src/onready/ - gestori degli eventi del gateway
  • src/embeds/ - l'embed principale
  • src/config/ - configurazione del cluster e stato condiviso del bot

Come avviene una risposta

Il gestore dei messaggi si attiva su ogni messaggio in ogni canale che il bot
può vedere. Ignora i bot, ignora tutto ciò che non la menziona tramite ping o
con le parole alisa o obliterator, e al momento ignora anche tutti gli autori
tranne uno, un id hardcoded in src/onmessage. Tutto ciò che sopravvive riceve
un embed immediato con scritto Thinking..., pubblicato prima che al modello
venga chiesto qualsiasi cosa, così il canale la vede prendere la domanda anche
quando la risposta è lenta.

La risposta stessa è una POST a Providence su http://127.0.0.1:8931 su
/speech/deepthink/, che trasporta il messaggio, l'intero contesto del club e
il nome utente Discord come identità del chiamante. Attende fino a 200 secondi.
La risposta viene troncata a 1990 byte su un confine di caratteri UTF-8 così
un taglio non cade mai a metà di un codepoint, e poi l'embed segnaposto viene
modificato sul posto. Un timeout, un rifiuto o un corpo non analizzabile
finiscono tutti come testo nello stesso embed piuttosto che nel silenzio.

Providence è un servizio separato e non è in questo repository. Senza di esso
in esecuzione su quella porta, il bot si avvia comunque, risponde comunque ai
comandi slash e continua comunque a fare scraping del club: smette solo di
pensare.

Cosa aggiunge Providence

Alisa invia light true, che è il percorso economico: un nodo di ragionamento e
nessuna ramificazione. Rimuovi quel flag e lo stesso endpoint esegue invece un
albero di pensieri limitato, profondità due, almeno due rami etichettati per
nodo, ciascuno valutato per probabilità di successo e per quanto potenziale
aggiunge o distrugge, e ogni nodo generato da un thinker nativo avviato come
sottoprocesso. Quel meccanismo è lì inutilizzato su ogni messaggio che invia.

Decide anche da sola se la domanda richiede più di una semplice conversazione.
Se sì, un classificatore mappa il messaggio su un comando e il suo argomento,
lo esegue e incorpora il risultato nella risposta finale. Cosa c'è in questo
elenco al momento:

  • grafici, una curva 2D o una superficie 3D da una funzione che descrivi a parole
  • algebra, semplificare, espandere, fattorizzare, risolvere per una variabile
  • calcolo, derivate, integrali definiti e indefiniti, limiti
  • matrici, determinante, inversa, autovalori
  • rendering di qualsiasi espressione come LaTeX
  • il portale UFFS SIGAA, discipline attuali, orario, compiti imminenti
  • il ristorante UFFS, quali pasti sono aperti per la prenotazione e come sono
    andati quelli passati, guidato tramite un vero browser headless con le proprie
    credenziali

Ognuna di queste risposte porta campi strutturati accanto alla prosa. Un grafico
o un rendering LaTeX torna come PNG base64 sotto image, una lettura del portale
torna come JSON sotto data, e il commento del modello stesso sta accanto sotto
response. Alisa legge response e butta via il resto, quindi oggi una domanda
che produce un grafico arriva su Discord come una frase su un grafico che
nessuno può vedere. Inviare l'immagine come allegato è la prossima cosa ovvia
che questo bot dovrebbe imparare.

L'accesso è per chiamante, non per bot. Si identifica come discord e il nome
utente dell'autore, e Providence controlla quella coppia e rifiuta chiunque non
conosca, che è il rifiuto che lei stampa testualmente. Aggiungere un membro del
club significa aggiungerlo lì, non qui.

Compilazione

Serve un compilatore C++20, CMake 3.16 o più recente, e tre librerie: DPP per
il gateway, cpr per HTTP, lexbor per HTML. Su Arch il Makefile installa quelle
mancanti tramite yay o paru. Altrove, installale tu prima.

make deps      recupera DPP, cpr e lexbor se assenti
make           configura e compila in build/
make run       carica .env, poi esegue il binario
make rebuild   cancella build/ e ricomincia

Due cose nella compilazione sono deliberate. Il tipo di build predefinito è
RelWithDebInfo, e i job di compilazione paralleli sono limitati a due. Gli
header di DPP sono abbastanza pesanti di template che una build non ottimizzata
costa diversi gigabyte per processo del compilatore, e un processo per core
porterà giù la macchina con sé. Dagliene di più quando hai memoria, make JOBS=8.

Le sorgenti vengono raccolte con CONFIGURE_DEPENDS, quindi un nuovo file sotto
src/ viene rilevato alla prossima compilazione senza toccare CMakeLists.

Configurazione

Il bot legge DISCORD_TOKEN dall'ambiente e nient'altro. Mettilo in .env nella
radice del repository e make run lo esporterà per te, oppure esportalo tu
stesso ed esegui build/alisa-v-zadzerkalli_core direttamente. Si connette con
gli intent predefiniti più il contenuto dei messaggi, che è un intent
privilegiato, quindi abilitalo sull'applicazione nel portale sviluppatori di
Discord o il gestore dei messaggi vedrà solo stringhe vuote.

Le chiavi di Providence stanno accanto a quelle in .env per il servizio
dall'altra parte della socket. Questo binario non le legge mai.