Я полагаю, что llama.cpp принудительно применяет схему, выбирая только токены, соответствующие ей. Я также перехватил ответ с помощью tcpdump и проверил, что возвращаемый ответ является валидным JSON.
Однако он содержал пробелы и переносы строк вне строк (т.е. это был JSON с форматированием), и эти переносы строк были экранированы Discourse, что сделало его невалидным (я проверил это в консоли Rails).
Кстати, я использую функцию обнаружения спама.