7.2 结构化输出解析与校验
模型输出需要被转换为类型安全的结构化形式才能可靠地驱动后续操作。本节介绍 Claude 的消息类型系统、非流式与流式响应的解析方法、Pydantic 参数验证以及完整的解析管道设计。
7.2.1 核心问题
原始 API 响应是无类型的字符串或弱类型的 JSON。要将其安全地转换为类型安全的结构化表示,需要解决:
类型识别:区分文本、工具调用、思考块等不同内容类型
增量解析:处理流式响应的片段化更新
结构校验:验证解析结果的完整性与合法性
向后兼容:支持不同 API 版本和模型的差异
7.2.2 Claude 的消息类型系统
Claude API 返回的消息(Message)由多个内容块(ContentBlock)组成,每个块有不同的类型:
from dataclasses import dataclass
from enum import Enum
from typing import Optional, List, Any
class ContentBlockType(Enum):
TEXT = "text"
TOOL_USE = "tool_use"
THINKING = "thinking"
@dataclass
class TextBlock:
"""文本内容块"""
type: str = "text"
text: str = ""
@dataclass
class ToolUseBlock:
"""工具调用块"""
type: str = "tool_use"
id: str = ""
name: str = ""
input: dict = None # JSON 输入参数
@dataclass
class ThinkingBlock:
"""思考过程块(Adaptive Thinking)"""
type: str = "thinking"
thinking: str = ""
ContentBlock = TextBlock | ToolUseBlock | ThinkingBlock
@dataclass
class ParsedMessage:
"""解析后的完整消息"""
content_blocks: List[ContentBlock]
stop_reason: str # "end_turn", "tool_use", "max_tokens"
tokens_used: int
def text_content(self) -> str:
"""提取所有文本内容"""
texts = [
block.text for block in self.content_blocks
if isinstance(block, TextBlock)
]
return "".join(texts)
def tool_calls(self) -> List[ToolUseBlock]:
"""提取所有工具调用"""
return [
block for block in self.content_blocks
if isinstance(block, ToolUseBlock)
]
def thinking_content(self) -> Optional[str]:
"""提取思考过程"""
for block in self.content_blocks:
if isinstance(block, ThinkingBlock):
return block.thinking
return None非流式解析
完整响应的解析实现方式如下:
流式解析
流式响应分块到达,需要增量构建完整消息。关键是跟踪当前正在构建的块状态:
使用流式解析器
流式解析器的具体使用方式如下:
Pydantic 校验
使用 Pydantic 定义预期的工具参数结构,并在解析后进行验证:
解析管道
完整的解析管道实现如下:
输出解析管道架构
结构化输出的解析流程如下所示:
图 7-2:输出解析管道 —— 从原始响应逐步转换为类型安全的结构化数据
总结
结构化输出解析通过:
类型系统 (TextBlock/ToolUseBlock/ThinkingBlock)提供类型安全
非流式与流式双路径 支持不同使用场景
增量解析 实现高效的流式处理
Pydantic 校验 确保参数合法性
这是构建可靠智能体的基础,为下一步的质量门控做准备。
最后更新于
