跳转到内容

Agno 结构化输出四层管线

Agno 结构化输出四层管线

学习目标

本章将分析 Agno 的结构化输出四层管线:

  • 四种方式实现结构化输出及其优先级
  • structured_outputs 利用模型原生支持
  • output_schema 通过 JSON Schema 注入系统提示
  • parser_model 使用二级模型解析响应
  • output_model 使用输出模型转换格式

前置知识

建议先阅读:

下文假设你已理解上述概念,直接聚焦 Agno 的具体实现。


项目实践

四层优先级

Agno 按以下优先级尝试结构化输出:

层级配置原理适用场景
1structured_outputs=True使用模型原生 API(如 OpenAI Responses 的 structured_outputs 参数)模型支持时最高质量
2output_schema=MyModel将 Pydantic model 转为 JSON Schema 注入系统提示通用方案,所有模型可用
3parser_model=...使用独立的二级模型解析主模型的响应主模型结构化能力弱时
4output_model=...使用输出模型转换响应需要格式转换时

structured_outputs:模型原生支持

# 伪代码:原生结构化输出
agent = Agent(
model=OpenAIResponses(id="gpt-4o"),
output_schema=WeatherResponse,
structured_outputs=True, # 使用 OpenAI 的 structured_outputs API
)

structured_outputs=True 时,Agno 将 Pydantic schema 传给模型的原生 API:

# 伪代码:模型调用
response = model.chat(
messages=messages,
response_format=output_schema, # OpenAI 原生参数
)

优势:模型内部优化结构化输出,质量更高 限制:只有部分模型支持(OpenAI、部分兼容模型)

output_schema:JSON Schema 注入

# 伪代码:JSON Schema 注入
agent = Agent(
model=OpenAIResponses(id="gpt-4o"),
output_schema=WeatherResponse,
parse_response=True,
)

Agno 将 Pydantic model 转为 JSON Schema 并注入系统提示:

# 伪代码:Schema 转字符串
schema_str = json.dumps(output_schema.model_json_schema())
system_message += f"\n请以以下 JSON Schema 格式返回响应:\n{schema_str}"

然后使用 pydantic 解析模型响应:

# 伪代码:响应解析
parsed = output_schema.model_validate_json(response.text)
return parsed

parser_model:二级模型解析

# 伪代码:二级模型解析
agent = Agent(
model=OpenAIResponses(id="gpt-4o"),
output_schema=WeatherResponse,
parser_model=OpenAIResponses(id="gpt-4o-mini"), # 用更便宜的模型解析
parser_model_prompt="将以上响应转换为 WeatherResponse 格式。",
)

流程:

  1. 主模型生成原始响应
  2. parser_model 接收原始响应 + schema,输出结构化格式
  3. 解析结果返回给调用方

优势:可以使用更便宜的模型做解析,降低成本

output_model:输出模型转换

# 伪代码:输出模型转换
agent = Agent(
model=OpenAIResponses(id="gpt-4o"),
output_schema=WeatherResponse,
output_model=OpenAIResponses(id="gpt-4o"),
output_model_prompt="将以上天气信息转换为标准格式。",
)

流程:

  1. 主模型生成响应
  2. output_model 接收响应 + 转换指令,输出转换后的格式

与 parser_model 的区别:parser_model 侧重于”解析为结构化格式”,output_model 侧重于”转换响应格式”。

use_json_mode

agent = Agent(
output_schema=WeatherResponse,
use_json_mode=True, # 不传 JSON Schema,改用系统提示中的 JSON 描述
)

use_json_mode=True 时,Agno 不将 Pydantic schema 转为 JSON Schema 传给模型,而是在系统提示中用自然语言描述格式。

适用场景:模型不支持 structured_outputs 参数,或 JSON Schema 导致模型输出质量下降。

问题与规避

1. structured_outputs 与模型不兼容

某些模型不支持 structured_outputs,开启后报错。

规避:Agno 的 determine_tools_for_model 中检查模型能力,自动降级为 JSON Schema 注入模式。

2. 复杂 Pydantic model 的 Schema 转义

嵌套 model、可选字段、自定义验证器的 JSON Schema 可能很复杂。

规避

  • 使用简单扁平 model
  • use_json_mode=True 避免 Schema 转义问题
  • 测试不同模型的 Schema 兼容性

3. parser_model 的双重 LLM 成本

使用 parser_model 会产生两次 LLM 调用。

规避

  • parser_model 使用更便宜的模型(如 gpt-4o-mini)
  • 只在主模型结构化能力弱时使用

设计取舍

为什么提供四种方式?

优势:不同场景不同需求——有原生 API 用原生,没有用 Schema 注入,都不行用二级模型 代价:用户需要理解四种方式的区别 替代方案:只提供两种方式——简单但可能在某些场景下效果不佳

为什么 parser_model 和 output_model 分开?

优势:关注点分离——解析(结构化)与转换(格式化)是两个不同的任务 代价:配置参数多 替代方案:合为一个参数——语义模糊

参考来源