
Alisa v Zadzerkalli (ucraniano) - Alice Através do Espelho. O mundo
do outro lado do espelho, onde você vai de propósito e tudo é
refletido, ao contrário e errado.
«Ніколи не вгадаєш, ким станеш за хвилину.»
"Você nunca pode adivinhar em quem você se tornará em um minuto." - Alice, em
Аліса в Країні Див, trad. Valentyn Korniienko, ed. Ivan Malkovych p. 53.
Um bot do Discord escrito em C++.
Recursos
Comandos de barra
- /ping - latência de ida e volta contra o gateway
- /leaderboard - a classificação do Clube de Programação (UFFS), extraída do
grupo vjudge do clube e classificada por problemas resolvidos
Conversa
Mencione-a, ou diga alisa ou obliterator em uma mensagem, e ela responde. A
resposta não é gerada localmente. Alisa monta o contexto e a Providência
faz o pensamento.
O que ela coloca diante do modelo em cada mensagem:
- cada membro do clube, em ordem de classificação, com seu handle, contagem de
problemas resolvidos e hora da última atividade - a lista completa de problemas que cada membro resolveu, por juiz
- os dez problemas mais resolvidos em todo o clube
Esse contexto é o que permite que ela responda perguntas para as quais ninguém
escreveu um comando. Quem está no top três, quais problemas eles têm em comum,
quem ficou quieto. O modelo fornece o raciocínio, a extração fornece os fatos.
Dados do clube
O estado dos membros é puxado do vjudge na inicialização por um pool limitado
de oito trabalhadores, cada um mantendo uma conexão para sua parte do grupo.
Cada membro custa duas requisições: a página de perfil para contagens e
classificação, e o endpoint de detalhes de resolução para a lista de problemas.
Estrutura
- main.cpp - ponto de entrada
- src/commands/ - comandos de barra e o despachante
- src/members/ - lista de membros do clube, extração de perfil e lista de resoluções
- src/parser/ - consulta HTML sobre lexbor
- src/network/ - HTTP com reutilização de conexão
- src/speech/ - o link da Providência e a montagem do prompt
- src/onmessage/, src/onready/ - manipuladores de eventos do gateway
- src/embeds/ - o embed padrão
- src/config/ - configuração do cluster e estado compartilhado do bot
Como uma resposta acontece
O manipulador de mensagens acorda a cada mensagem em cada canal que o bot pode
ver. Ele descarta bots, descarta qualquer coisa que não o mencione por ping ou
pelas palavras alisa ou obliterator, e no momento também descarta todos os
autores exceto um, um id codificado em src/onmessage. O que sobrevive recebe
um embed imediato lendo Pensando..., postado antes de o modelo ser consultado,
para que o canal veja que ela pegou a pergunta mesmo quando a resposta é lenta.
A resposta em si é um POST para a Providência em http://127.0.0.1:8931 em
/speech/deepthink/, carregando a mensagem, todo o contexto do clube e o
nome de usuário do Discord como identidade do chamador. Ela espera até 200
segundos. A resposta é cortada em 1990 bytes em um limite de caractere UTF-8
para que um corte nunca caia no meio de um codepoint, e então o embed
placeholder é editado no lugar. Um timeout, uma recusa ou um corpo não
analisável terminam como texto no mesmo embed, em vez de silêncio.
A Providência é um serviço separado e não está neste repositório. Sem ela
rodando nessa porta, o bot ainda inicia, ainda responde a comandos de barra e
ainda extrai o clube; ele apenas para de pensar.
O que a Providência adiciona
Alisa envia light true, que é o caminho barato, um nó de raciocínio e sem
ramificação. Remova essa flag e o mesmo endpoint executa uma árvore limitada de
pensamentos, profundidade dois, pelo menos dois ramos rotulados por nó, cada um
pontuado por probabilidade de sucesso e por quanto potencial ele adiciona ou
destrói, e cada nó gerado por um pensador nativo criado como subprocesso. Essa
máquina fica ali, sem uso, em cada mensagem que ela envia.
Ela também decide por si mesma se a pergunta precisa de mais do que conversa.
Se precisar, um classificador mapeia a mensagem para um comando e seu
argumento, executa-o e incorpora o resultado na resposta final. O que está
nessa lista agora:
- plotagem, uma curva 2D ou uma superfície 3D a partir de uma função que você
descreve em palavras - álgebra, simplificar, expandir, fatorar, resolver para uma variável
- cálculo, derivadas, integrais definidas e indefinidas, limites
- matrizes, determinante, inversa, autovalores
- renderização de qualquer expressão como LaTeX
- o portal SIGAA da UFFS, disciplinas atuais, horários, tarefas futuras
- o restaurante da UFFS, quais refeições estão abertas para reserva e como as
passadas foram, dirigido por um navegador headless real com suas próprias
credenciais
Cada uma dessas respostas carrega campos estruturados ao lado da prosa. Um
gráfico ou uma renderização LaTeX volta como um PNG base64 sob image, uma
leitura do portal volta como JSON sob data, e o comentário do próprio modelo
fica ao lado sob response. Alisa lê response e joga o resto fora, então hoje
uma pergunta que produz um gráfico chega ao Discord como uma frase sobre um
gráfico que ninguém pode ver. Enviar a imagem como anexo é a próxima coisa
óbvia que este bot deveria aprender.
O acesso é por chamador, não por bot. Ela se identifica como discord e o nome
de usuário do autor, e a Providência verifica esse par e recusa qualquer um que
não conheça, que é a recusa que ela imprime literalmente. Adicionar um membro
do clube significa adicioná-lo lá, não aqui.
Compilação
Requer um compilador C++20, CMake 3.16 ou mais novo, e três bibliotecas: DPP
para o gateway, cpr para HTTP, lexbor para HTML. No Arch, o Makefile instala
as que estiverem faltando via yay ou paru. Em qualquer outro lugar, instale-as
você mesmo primeiro.
make deps busca DPP, cpr e lexbor se ausentes
make configura e compila em build/
make run carrega .env, então executa o binário
make rebuild limpa build/ e recomeça
Duas coisas na compilação são deliberadas. O tipo de build padrão é
RelWithDebInfo, e os trabalhos de compilação paralela são limitados a dois. Os
cabeçalhos do DPP são pesados em templates o suficiente para que um build não
otimizado custe vários gigabytes por processo do compilador, e um processo por
núcleo derrubará a máquina junto. Dê mais quando tiver memória, make JOBS=8.
As fontes são coletadas com CONFIGURE_DEPENDS, então um novo arquivo em src/ é
captado no próximo build sem tocar no CMakeLists.
Configuração
O bot lê DISCORD_TOKEN do ambiente e nada mais. Coloque-o em .env na raiz do
repositório e make run o exportará para você, ou exporte você mesmo e execute
build/alisa-v-zadzerkalli_core diretamente. Ela se conecta com os intents
padrão mais conteúdo de mensagem, que é um intent privilegiado, então habilite-o
no aplicativo no portal de desenvolvedores do Discord ou o manipulador de
mensagens só verá strings vazias.
As chaves da Providência ficam ao lado dele em .env para o serviço na outra
ponta do socket. Este binário nunca as lê.
