首页 / 文章 / 结构化输出 vs 工具使用 vs 预填充:2026年从Claude获取JSON
← 返回
AI技术

结构化输出 vs 工具使用 vs 预填充:2026年从Claude获取JSON

✍️ zhirenhun 📅 2026/7/11 👁 12 阅读 ⏱ 10 分钟
结构化输出 vs 工具使用 vs 预填充:2026年从Claude获取JSON

结构化输出 vs 工具使用 vs 预填充:2026年从Claude获取JSON

长期以来,强制模型输出JSON的技巧是在助手轮次中预填充一个左花括号。但这个技巧在当前版本的Claude模型上已经失效了,会返回400错误。如果你还在使用这种方法,一旦升级模型版本,代码就会崩溃。本文将介绍获取可靠结构化输出的现代方法,以及如何在替代预填充的两种方案中做出选择。


问题所在

旧的模式:

// 在 Opus 4.6+、Fable 5 上错误:预填充最后助手轮次现在会返回400
messages: [
  { role: "user", content: "提取名称。" },
  { role: "assistant", content: '{"name": "' }, // 强制JSON起始
]

我第一次在Opus 4.8上尝试时,这段代码就返回了400。Opus 4.6、4.7、4.8和Fable 5不再支持最后助手轮次的预填充。替代方案取决于预填充原本要实现的目的。


方案1:结构化输出(当你需要特定格式时)

如果预填充是为了强制JSON schema,直接的替代方案是使用 output_config.format。SDK会自动根据你的schema验证响应,配合Zod还能免费获得类型安全:

import { z } from "zod";
import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";

const Finding = z.object({
  vulnerability: z.string(),
  severity: z.enum(["low", "medium", "high", "critical"]),
  function_name: z.string(),
  line: z.number(),
});

const response = await client.messages.parse({
  model: "claude-opus-4-8",
  max_tokens: 16000,
  messages: [{ role: "user", content: `查找漏洞:

${contract}` }],
  output_config: { format: zodOutputFormat(Finding) },
});

// 类型安全且经过验证。解析失败时为null。
console.log(response.parsed_output?.severity);

输出保证匹配schema,否则 parsed_output 为null。无需正则表达式,无需在try/catch中写JSON.parse,也无需担心"模型又加了markdown代码块"。

需要注意一些schema限制:数值约束(如最小值/最大值)不会在服务端强制执行(SDK会移除这些约束并在客户端验证),不支持递归schema,每个对象都需要设置 additionalProperties: false。Zod辅助函数会帮你处理大部分问题。


方案2:工具调用(当JSON是操作的副作用时)

如果你真正想要的是让模型使用结构化参数执行某个操作,那么工具调用是更合适的选择。典型的场景是分类:你需要一个标签,而这个标签就是工具的输入。

const response = await client.messages.create({
  model: "claude-opus-4-8",
  max_tokens: 1024,
  tools: [{
    name: "classify_severity",
    description: "记录发现的严重程度分类。",
    strict: true,
    input_schema: {
      type: "object",
      properties: {
        severity: { type: "string", enum: ["low", "medium", "high", "critical"] },
      },
      required: ["severity"],
      additionalProperties: false,
    },
  }],
  tool_choice: { type: "tool", name: "classify_severity" },
  messages: [{ role: "user", content: `分类:

${finding}` }],
});

使用 strict: true 可以保证参数完全符合schema。将 tool_choice 强制指定为特定工具,意味着模型必须调用它。


如何选择

决定性的问题是:JSON是最终答案,还是某个操作的参数?

  • JSON是我要解析并直接使用的结构化对象? → 使用结构化输出(output_config.format)。
  • 模型是循环中的一个步骤,JSON需要传递给下一个工具? → 使用工具调用。
  • 我要从文本中提取字段并存入记录? → 使用结构化输出。
  • 我在构建一个需要在多个操作中选择的智能体? → 使用工具调用。

对于我的审计工具,报告就是最终答案,所以我使用结构化输出。对于决定运行哪个分析流程的路由逻辑,决策本身是一个操作,所以我使用工具调用。


其他预填充技巧的替代方案

预填充不仅用于JSON,以下是完整的映射关系:

  • 强制分类标签:使用带enum的工具,或结构化输出。
  • 跳过开场白(如"以下是摘要:"):在系统提示中写明"直接回复,无需开场白"。
  • 规避不当拒绝:现在通常不需要;当前模型的拒绝行为更加合理,直接提示即可。
  • 继续被中断的回复:在用户轮次中放入续写内容,如"你之前的回复以X结尾,请从这里继续"。

总结

预填充技巧利用的是模型续写文本的方式。而现代功能通过在API层面约束输出格式来实现目标,既更可靠,也不会因模型升级而失效。如果你还在预填充花括号,那么只需一次模型字符串的更改,就会遇到400错误。请改用结构化输出或工具调用,别再和格式化器较劲了。

原文:https://dev.to/pavelespitia/structured-outputs-vs-tool-use-vs-prefills-getting-json-out-of-claude-in-2026-5fi0

——

🧑‍💻

zhirenhun

一个热爱技术的程序员,喜欢分享前沿AI知识和开发经验。

← 上一篇
在AWS Bedrock上构建生产级AI代理——值得关注的架构与代码决策

📌 相关推荐

在AWS Bedrock上构建生产级AI代理——值得关注的架构与代码决策
2026/7/11
如何为你的AI代理构建评估框架(确保其在生产环境中不崩溃)
2026/7/11
我把一个仅限Claude Code使用的网页阅读器变成了一个普通的MCP服务器
2026/7/11
← 返回文章列表