toMedia
Claude API

结构化输出

保证 Claude 输出严格符合 JSON Schema — Pydantic/Zod 集成与 Strict 工具模式

概述

结构化输出确保 Claude 的响应严格遵循指定的 JSON Schema,消除解析错误和类型不匹配。

Python + Pydantic

import anthropic
from pydantic import BaseModel

class ContactInfo(BaseModel):
    name: str
    email: str
    company: str
    plan_interest: str
    demo_requested: bool

client = anthropic.Anthropic()

response = client.messages.parse(
    model="claude-opus-4-6",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": "提取联系人信息:张三,zhang@example.com,在字节工作,对高级方案感兴趣,需要演示"
    }],
    output_format=ContactInfo,
)

# 类型安全的访问
contact = response.parsed_output
print(f"姓名: {contact.name}")
print(f"邮箱: {contact.email}")
print(f"公司: {contact.company}")
print(f"需要演示: {contact.demo_requested}")

TypeScript + Zod

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

const ContactSchema = z.object({
  name: z.string(),
  email: z.string().email(),
  company: z.string(),
  plan_interest: z.string(),
  demo_requested: z.boolean(),
});

const client = new Anthropic();

const response = await client.messages.parse({
  model: "claude-opus-4-6",
  max_tokens: 1024,
  messages: [{
    role: "user",
    content: "提取联系人信息:张三,zhang@example.com,字节跳动,高级方案,需要演示",
  }],
  output_format: ContactSchema,
});

const contact = response.parsed;
console.log(`姓名: ${contact.name}`);

嵌套结构提取

from pydantic import BaseModel
from typing import List

class Product(BaseModel):
    name: str
    price: float
    quantity: int

class Invoice(BaseModel):
    invoice_number: str
    customer_name: str
    total_amount: float
    items: List[Product]
    is_paid: bool

response = client.messages.parse(
    model="claude-opus-4-6",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": """提取发票数据:
        发票号 #12345
        客户:李四
        商品:
        - 笔记本电脑:¥8999 x 1
        - 鼠标:¥199 x 2
        - 键盘:¥599 x 1
        总计:¥9996
        状态:已付款"""
    }],
    output_format=Invoice,
)

invoice = response.parsed_output
print(f"发票: {invoice.invoice_number}")
for item in invoice.items:
    print(f"  - {item.name}: ¥{item.price} x {item.quantity}")

分类任务

from typing import Literal

class EmailClassification(BaseModel):
    category: Literal["spam", "promotional", "important", "general"]
    confidence: float
    reasoning: str

emails = [
    "恭喜你中了100万!点击领取!",
    "明天下午2点在B会议室开会",
    "全场8折优惠,使用码 SAVE20",
]

for email in emails:
    response = client.messages.parse(
        model="claude-opus-4-6",
        max_tokens=256,
        messages=[{
            "role": "user",
            "content": f"分类这封邮件: {email}",
        }],
        output_format=EmailClassification,
    )
    result = response.parsed_output
    print(f"邮件: {email[:30]}...")
    print(f"分类: {result.category}(置信度: {result.confidence})")
    print(f"原因: {result.reasoning}\n")

Strict 工具模式

保证工具输入严格符合 Schema:

tools = [
    {
        "name": "get_weather",
        "description": "获取天气",
        "strict": True,  # 启用严格模式
        "input_schema": {
            "type": "object",
            "properties": {
                "location": {"type": "string", "description": "城市名"},
                "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
            },
            "required": ["location"],
            "additionalProperties": False  # 禁止额外字段
        }
    }
]

response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    tools=tools,
    messages=[{"role": "user", "content": "上海天气怎么样?"}]
)

# 工具输入保证符合 Schema,无需额外验证
for block in response.content:
    if block.type == "tool_use":
        print(f"工具: {block.name}")
        print(f"输入(保证有效): {block.input}")

最佳实践

  1. 类型安全:用 Pydantic(Python)或 Zod(TypeScript)定义 Schema
  2. 字段描述:帮助 Claude 理解每个字段应该包含什么
  3. Enum 分类:预定义选项使用 enum
  4. 嵌套结构:通过 BaseModel 组合支持复杂层级
  5. Strict 工具:关键 Agent 工作流中使用,确保下游系统不会收到非法输入

On this page