Acredito que o llama.cpp force o esquema, selecionando apenas tokens que estejam em conformidade com ele. Também capturei uma resposta com o tcpdump e verifiquei que a resposta retornada é um JSON válido.
No entanto, ela continha espaços e quebras de linha fora das strings (ou seja, era um JSON formatado), e essas quebras de linha foram escapadas pelo Discourse, tornando-o inválido (verifiquei no console do Rails).
Aliás, estou usando a função de detecção de spam.