系列: 100 天系统学习 AI Agent 开发
当前阶段: Agent 基础与环境搭建
今日目标: 掌握结构化输出,把模型回答变成可被代码解析的对象,为后续工具调用和业务接入打下地基。
AI Agent 大模型 Agent开发

很多刚接触大模型开发的朋友都有个痛点:在控制台跑 Demo 时效果惊艳,但一接到后端业务里就抓瞎。为什么?因为大模型默认输出的是“一段漂亮的自然语言”,而我们的系统逻辑需要的是精准、可解析的数据结构(比如 JSON)。

如果 Agent 只会写小作文,那它永远只是个聊天机器人。 今天,我们就来攻克 Agent 走向自动化的第一步:结构化输出。


一、 核心概念:为什么必须“结构化”?

为了避免照本宣科,我用自己的话总结结构化输出在工程中的核心定位(3句话):

  1. 它是连接桥梁:结构化输出是将大模型(非确定性的自然语言处理)与传统软件工程(确定性的代码逻辑)连接起来的唯一通道。
  2. 它是分工界限:它强迫我们将任务拆解——模型只负责“理解意图”和“生成关键参数”,而复杂的逻辑流转交还给代码。
  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)。
Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐