kita / notes

约 2 分钟

我以为"让模型返回 JSON"是最简单的一个活

后端有个小功能,要把一段文字交给大模型解析成结构化数据。我接这个活的时候想的是"这个最快"。

结果它是整个项目里我唯一没修好的东西。

第一次请求,后端返回:

Overstats API 错误: 500 - shiqu_llm_not_configured

它说我没配 LLM。那就配上,填 key,选模型。再请求,变成:

502 - shiqu_llm_failed ... 返回内容不是合法 JSON

这次模型调通了,是它返回的东西后端解析不了。

我用的第一个模型是 deepseek-v4-flash。我查了一下,它不支持强制 JSON 输出——你要求它返回 JSON,它会给一段"看着像 JSON 的文字"。听起来就是它了。

换成硅基流动上的 Qwen2.5-7B-Instruct,还是 502。

到这里我判断问题在解析环节。最可能的形态是模型给返回值裹了一层 Markdown 代码块:

```json
{ "区": true }
```

它觉得这样更"友好",后端的 json.loads() 直接崩。这也解释了为什么换模型没用——很多模型默认都会这么干。

我后来想到该怎么防

约束那一头:选明确支持结构化输出参数的模型,别指望所有模型都听话;提示词里写死"只返回纯 JSON,不要解释、不要 Markdown 代码块";超时调大(我调到 600 秒,慢模型出结构化内容更慢)。

解析那一头:在 json.loads 之前先剥掉代码块围栏,把开头的 ```json 和结尾的 ``` 去掉再解析。

还有一条是我这次最缺的:解析失败的时候,把原始返回内容打进日志。

我全程只能猜,就是因为日志里只有"不是合法 JSON"这一句,没有那段内容本身。如果有原文,看一眼就知道该剥什么了。

这功能到现在还放着,我暂时改用不依赖 LLM 的那几个指令。


同一时期我还在配图源插件,撞上一个同类的事。插件面板一直提示 "Pixiv Token 未配置",我去拿 token:

gppt login -j

输出第一行就是:

Cached token expired; refreshing ...

给出新的 access_token 和 refresh_token,我复制进插件——还是不行。中间命令行飞快闪过一句:

Reusing the cached token

它在复用本地缓存里的旧 token。我反复重试、反复复制,复制来复制去还是失效的那一版。直接拿 refresh_token 手动去换新的也不通:

指定されたエンドポイントは存在しません

"指定的端点不存在"——接口已经变了。

最后我把这个 token 清空,只用主图源。少一个回退源,但少一堆麻烦。


这两件事我放在一起记,是因为性质一样:模型答应给你 JSON 是约定,第三方给你长期 token 也是约定。这两种约定都会静默失效——不报错,不提醒,只是安静地不工作。

所以我后来给任何依赖外部服务的环节加的第一样东西,是让它能"证明自己还活着":一个健康检查,或者一条带原始返回的日志。比事后翻记录猜原因省事太多。

← 回到全部笔记