一句话结论
使用 GLM-4.7-Flash 做文章分类、AI 摘要或数据提取时,不要只在提示词里写“只输出 JSON”。本站生产环境实测发现,这种方式可能返回 Markdown 代码围栏,导致 JSON.parse 直接失败。启用 response_format: { type: "json_object" } 能得到合法 JSON,但仍要验证字段结构和业务取值。
如果你还没有完成模型接入,请先看 GLM-4.7-Flash API 配置与实测;需要多个模型容错时,可继续阅读 Node.js 多模型轮询与故障切换。
两种方式的真实对比
测试时间为 2026 年 8 月 13 日,环境为本站生产服务器 Node.js 20 容器,模型为 glm-4.7-flash,关闭思考模式。
| 调用方式 | HTTP | 延迟 | 能否直接 JSON.parse | 实际表现 |
|---|---|---|---|---|
| 只用提示词要求 JSON | 200 | 1995 ms | 否 | 返回了 Markdown 代码围栏 |
| response_format JSON 模式 | 200 | 1547 ms | 是 | 返回合法 JSON,但增加了 answer 外层 |
这说明接口成功、语法合法和字段符合预期是三件不同的事。JSON 模式解决的是语法问题,不会自动保证对象结构完全符合你的程序。
正确的 Node.js 请求方式
const response = await fetch(
'https://open.bigmodel.cn/api/paas/v4/chat/completions',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.ZHIPU_API_KEY}`,
},
body: JSON.stringify({
model: 'glm-4.7-flash',
messages: [
{
role: 'system',
content: '你是文章分类器。必须输出有效 JSON。',
},
{
role: 'user',
content: '将文章分到允许分类中,并给出不超过3个标签。',
},
],
response_format: { type: 'json_object' },
thinking: { type: 'disabled' },
temperature: 0.2,
max_tokens: 300,
}),
signal: AbortSignal.timeout(30_000),
},
);
if (!response.ok) {
throw new Error(`模型请求失败:${response.status}`);
}
const payload = await response.json();
const content = payload.choices?.[0]?.message?.content;
if (!content) throw new Error('模型返回内容为空');
const result = JSON.parse(content);
系统提示词中仍应明确要求 JSON。智谱官方文档说明 JSON 模式会返回有效 JSON,但程序不能因此跳过后续校验。
为分类结果做业务校验
假设网站只允许四个分类:
const allowedCategories = new Set([
'AI 开发教程',
'AI 工程实践',
'AI 工具与应用',
'行业观察',
]);
function validateClassification(value) {
const candidate = value.answer ?? value;
if (!candidate || typeof candidate !== 'object') {
throw new Error('分类结果不是对象');
}
if (!allowedCategories.has(candidate.category)) {
throw new Error(`不允许的分类:${candidate.category}`);
}
if (!Array.isArray(candidate.tags)) {
throw new Error('tags 必须是数组');
}
const tags = candidate.tags
.filter(tag => typeof tag === 'string')
.map(tag => tag.trim())
.filter(Boolean)
.slice(0, 3);
return { category: candidate.category, tags };
}
这里兼容了实测出现的 answer 外层,但更稳妥的做法是使用 JSON Schema 校验库,并把允许分类动态写进提示词。
兼容已有的 Markdown 输出
旧提示词或其他模型可能继续返回代码围栏。迁移期间可以做一次保守清理:
function parseModelJson(text) {
const cleaned = String(text)
.trim()
.replace(/^```jsons*/i, '')
.replace(/s*```$/, '');
return JSON.parse(cleaned);
}
不要用正则从任意长文本中贪婪截取第一对花括号,这容易把解释文字或嵌套对象截坏。解析失败时应保留脱敏后的原始输出用于排查,然后有限重试或进入人工审核。
AI 摘要应该校验哪些字段
日报或文章摘要不应只检查“有内容”。至少验证:
intro是非空字符串,并限制最大长度;highlights是数组,条数符合后台配置;- 每条精选包含标题、摘要和来源 ID;
- 来源 ID 必须存在于本次抓取数据,避免模型编造链接;
- 分类必须属于网站的固定分类集合;
- 输出中不能包含 API Key、后台 Token 等敏感信息。
当某一字段不合格时,优先让模型只修复该字段,而不是重新生成整篇日报。这样更节省 Token,也减少已经合格内容发生变化。
为什么 content 有时是空的
开启思考模式后,模型可能先把 Token 用在 reasoning_content。如果 max_tokens 太小,最终 content 可能为空。分类、标签和固定结构提取通常不需要复杂推理,可以关闭思考模式;如果必须开启,则同时检查 reasoning_content、finish_reason 和 Token 用量。
重试策略
以下情况可以重试一次:网络超时、临时 5xx、JSON 被截断。以下情况不应该原样重试:提示词没有给出允许字段、分类集合不完整、Schema 与程序代码不一致。后者必须先修正请求,否则多模型轮询只会重复产生错误结果。
建议每次请求记录:配置模型、响应模型、HTTP 状态、finish_reason、解析结果、Schema 校验结果、延迟和 Token 用量。日志中不要写入 API Key,也尽量避免保存包含个人信息的完整正文。
适合本站后台的落地流程
- 抓取阶段只保存原始数据,不调用模型;
- AI 总结阶段使用 JSON 模式生成结构化结果;
- 服务端解析并执行字段、分类和来源 ID 校验;
- 校验失败只重试一次,并显示实际使用模型;
- 仍失败则保留抓取数据,允许管理员重新总结;
- 通过后再写入日报或文章库,避免半成品覆盖旧内容。
最终建议
GLM-4.7-Flash 的 JSON 模式适合自动分类、摘要和字段提取,但它只是可靠链路的一环。生产环境应同时使用明确提示词、response_format、关闭不必要的思考、服务端 Schema 校验、允许值集合和有限重试。只有这些步骤全部通过,模型输出才能安全落库。
常见问题
response_format 能保证字段完全正确吗?
不能。它主要保证 JSON 语法有效,模型仍可能增加外层对象、遗漏字段或返回不允许的分类,因此服务端必须继续做 Schema 和白名单校验。
为什么提示词要求 JSON 仍会返回代码围栏?
自然语言约束不是协议约束,模型可能按常见写作格式包裹 Markdown。应使用 JSON 模式,并为旧输出提供有限的代码围栏清理。
JSON 解析失败后应该重新生成整篇内容吗?
优先只重试失败字段或结构修复。整篇重新生成会增加 Token 成本,也可能改变已经合格的内容。