我昨天更新了,现在日志中出现了大量错误:
Discourse AI: structured output response was not valid JSON, falling back to best-effort parsing (311 bytes)
我检查了 HTTP 响应,发现没有问题。然后我在 rails console 中尝试解析这段文本:
...
discourse(prod)> p = JsonCompleter.new
=>
#<JsonCompleter:0x00007f48763b0270
...
discourse(prod)> p.parse text
=>
{"spam" => false,
"reason" =>
"..."}
discourse(prod)> p.parse DiscourseAi::Utils::BestEffortJsonParser.escape_control_characters(text)
(discourse):14:in '<main>': unexpected token "\\" (JsonCompleter::ParseError)
原来,Discourse 在解析之前转义了换行符^[code,这是由 pr#41716 引入的,导致了该错误。
Falco
(Falco)
2
那是一个警告,不是错误。
不过,鉴于大家一直对此感到担忧,我将把它的日志级别调整为 INFO 
嗯,从技术上来说确实如此,但这表明代码中存在一个 bug。后备机制有效,因此没有引发错误,但最好还是修复源头,而不是将其降级为 INFO 级别来掩盖问题,对吧?
JSON 允许将换行符作为空白字符,但不允许在字符串外部使用转义序列;然而,转义函数却对其进行了转义。要修复此问题,你可以改为仅转义 JSON 规范中规定的 0x0 到 0x1f(含)之间的 ASCII 字符。(我不知道如何用 Ruby 编写,所以没有提交 PR。)
为了说明这一点,以下是有效的 JSON:
{
"key": "value"
}
以下是一个转义后的 JSON,它是无效的,并导致了问题:
{\u000a "key": "value"\u000a}
llama-server -hf mradermacher/Qwen3-4B-Instruct-2507-GGUF:Q4_K_M
sam
(Sam Saffron)
7
4B 模型在遵循指令方面可能会比较吃力,虽然这类模型正在不断进步,但这确实属于较旧的版本。
如果你打算使用 4B 模型,我可能更推荐一些较新的选择……试试 Qwen 3.5-4B 或 Gemma 4 E4B。
我认为 llama.cpp 通过仅选择符合该模式的标记来强制实施模式。我还使用 tcpdump 捕获了一个响应,并确认返回的响应是有效的 JSON。
然而,它在字符串外部包含空格和换行符(即它是美观打印的 JSON),而 Discourse 转义了这些换行符,使其无效(我在 Rails 控制台中进行了检查)。
顺便说一句,我正在使用垃圾邮件检测功能。