Day 004:让 Agent 告别“漂亮废话”,搞定结构化输出
系列: 100 天系统学习 AI Agent 开发
当前阶段: Agent 基础与环境搭建
今日目标: 掌握结构化输出,把模型回答变成可被代码解析的对象,为后续工具调用和业务接入打下地基。AI Agent大模型Agent开发
很多刚接触大模型开发的朋友都有个痛点:在控制台跑 Demo 时效果惊艳,但一接到后端业务里就抓瞎。为什么?因为大模型默认输出的是“一段漂亮的自然语言”,而我们的系统逻辑需要的是精准、可解析的数据结构(比如 JSON)。
如果 Agent 只会写小作文,那它永远只是个聊天机器人。 今天,我们就来攻克 Agent 走向自动化的第一步:结构化输出。
一、 核心概念:为什么必须“结构化”?
为了避免照本宣科,我用自己的话总结结构化输出在工程中的核心定位(3句话):
- 它是连接桥梁:结构化输出是将大模型(非确定性的自然语言处理)与传统软件工程(确定性的代码逻辑)连接起来的唯一通道。
- 它是分工界限:它强迫我们将任务拆解——模型只负责“理解意图”和“生成关键参数”,而复杂的逻辑流转交还给代码。
- 它是自动化的基石:没有结构化输出,后端的 API 调用、数据库写入、数据自动评测都无从谈起,只能依赖人工干预。
二、 工程视角:认清模型的责任边界
在实际开发中,最容易踩的坑就是“把所有事都交给大模型”。落实到结构化输出,我们需要明确一套责任划分和最小闭环:
- 大模型的责任:阅读上下文,提取关键信息,并严格按照我们给定的 Schema 输出。
- 代码的责任:解析输出、字段类型校验、默认值兜底、权限控制以及错误重试。
一个真正的 Agent 最小闭环必须跑通这五步:输入 -> 模型决策(输出结构化参数) -> 代码解析并调用工具 -> 观察执行结果 -> 再次输出。如果今天这步(输出结构化参数)没做扎实,后面的工具(Tools)和记忆(Memory)模块都会变成空中楼阁。
三、 动手实战:设计一个任务规划的 JSON Schema
今天的主任务是设计一个 JSON Schema,用于让 Agent 对复杂任务进行拆解。
需求字段:
task_name: 任务名称steps: 具体的执行步骤列表risk_level: 风险等级评估next_action: 下一步具体动作
在实际的 Python 工程中,我们通常会结合 Pydantic 来定义和验证,以下是我今天跑通的最小可复用产物:
from pydantic import BaseModel, Field
from typing import List, Literal
# 1. 定义期望的结构化数据模型
class TaskPlanSummary(BaseModel):
task_name: str = Field(..., description="用户请求的核心任务名称")
steps: List[str] = Field(..., description="完成该任务所需按顺序执行的具体步骤")
risk_level: Literal["Low", "Medium", "High"] = Field(
..., description="执行该任务的潜在风险等级"
)
next_action: str = Field(..., description="Agent 接下来应该立即执行的具体动作或调用的工具名")
# 2. 对应的 JSON Schema (可以传给 OpenAI/本地模型的 tools 接口)
task_schema = TaskPlanSummary.model_json_schema()
import json
print(json.dumps(task_schema, indent=2, ensure_ascii=False))
有了这个 Schema 约束,模型就不再回复“好的,我将为您执行以下任务…”,而是老老实实返回类似这样的纯净数据:
{
"task_name": "分析最新的销售数据",
"steps": ["下载销售报表", "提取Q3数据", "生成趋势图"],
"risk_level": "Low",
"next_action": "call_download_api"
}
四、 避坑笔记(干货预警)
很多新手跑通了上面的格式就以为万事大吉了,但一旦接入真实环境,立马就会遇到报错。今天的核心避坑指南只有一句:结构化输出不是万能保险,仍然必须在代码层做字段校验、默认值和异常兜底。
- 幻觉字段:模型有时会自作主张多输出几个字段。一定要在反序列化时开启严格模式(比如 Pydantic 的
extra="forbid"或选择忽略多余字段)。 - Markdown 代码块包裹:模型很喜欢在 JSON 外面套上
json。在传给json.loads()之前,一定要写个正则清洗掉这些标记,或者使用各大平台最新的response_format={ "type": "json_object" }强制纯 JSON 输出。 - 类型漂移:要求输出数组,它偶尔给你输出逗号分隔的字符串。这就需要代码层捕获解析异常(Parse Error),并把错误信息塞回给大模型让它重试(Retry)。
更多推荐


所有评论(0)