结构化输出让Agent返回可预测的格式数据

介绍:你是否有过这样的经历(让AI提取联系人信息,它返回用户叫张三,邮箱是zhangsan@qq.com,电话是123456,下次再问,格式变成了"姓名:张三 | 邮箱:zhangsan@qq.com")

结构化输出正是解决这一痛点的利器。Spring AI Alibaba为ReactAgent提供了两种优雅的方式,让AI智能体输出可直接解析的JSON数据,应用程序可以像调用普通API一样消费AI能力。

步骤一:结构化输出

结构化输出允许Agent以特定的、可预测的格式返回数据。相比于解析自然语言响应,你可以直接获得JSON对象或POJO。

java 复制代码
// 未使用结构化输出(返回自然语言)
"用户张三,邮箱zhangsan@example.com,电话(555) 123-4567"

// 使用结构化输出(返回JSON)
{"name": "张三", "email": "zhangsan@example.com", "phone": "(555) 123-4567"}

后者可以使用Jackson反序列化为Java对象,无缝接入业务逻辑。

步骤二:两种方式

Spring AI Alibaba提供了两种控制结构化输出的方式:

方式 说明 推荐度
outputType(Class) 传入Java类,框架自动转换为JSON Schema ⭐⭐⭐⭐⭐
outputSchema(String) 手动提供JSON Schema字符串 ⭐⭐⭐

[1]outputType

最简洁的方式,直接传入Java类,框架使用BeanOutputConverter自动处理一切:

java 复制代码
import com.alibaba.cloud.ai.graph.agent.ReactAgent;
import org.springframework.ai.chat.messages.AssistantMessage;

// 1. 定义输出结构(标准POJO)
public static class ContactInfo {
    private String name;
    private String email;
    private String phone;
    
    // 必须提供getter/setter
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public String getPhone() { return phone; }
    public void setPhone(String phone) { this.phone = phone; }
}

// 2. 创建Agent并指定outputType
ReactAgent agent = ReactAgent.builder()
    .name("contact_extractor")
    .model(chatModel)
    .outputType(ContactInfo.class)  // 直接传入Class
    .saver(new MemorySaver())
    .build();

// 3. 调用并获取结构化结果
AssistantMessage result = agent.call(
    "提取联系方式:张三,zhangsan@example.com,(555) 123-4567"
);

System.out.println(result.getText());
// 输出: {"name": "张三", "email": "zhangsan@example.com", "phone": "(555) 123-4567"}

方式二:outputSchema

当需要完全自定义输出格式时,可以手动提供JSON Schema:

java 复制代码
import org.springframework.ai.converter.BeanOutputConverter;

// 定义POJO(同上ContactInfo)
BeanOutputConverter<ContactInfo> converter = 
    new BeanOutputConverter<>(ContactInfo.class);
String schema = converter.getFormat();  // 自动生成Schema

ReactAgent agent = ReactAgent.builder()
    .name("contact_extractor")
    .model(chatModel)
    .outputSchema(schema)  // 使用生成的Schema
    .build();

步骤三:实战

案例1:产品评价分析

java 复制代码
public static class ProductReview {
    private int rating;              // 评分 1-5
    private String sentiment;       // 情感倾向
    private String[] keyPoints;     // 关键点
    private ReviewDetails details;  // 嵌套详情
    
    // getters/setters...
    
    public static class ReviewDetails {
        private String[] pros;   // 优点
        private String[] cons;   // 缺点
        // getters/setters...
    }
}

ReactAgent agent = ReactAgent.builder()
    .name("review_analyzer")
    .model(chatModel)
    .outputType(ProductReview.class)
    .build();

AssistantMessage result = agent.call(
    "分析评价:这个产品很棒,5星好评。配送快速,但价格稍贵。"
);

// 输出示例:
// {
//   "rating": 5,
//   "sentiment": "正面",
//   "keyPoints": ["产品很棒", "配送快速", "价格稍贵"],
//   "details": {
//     "pros": ["产品品质", "配送速度"],
//     "cons": ["价格"]
//   }
// }

案例2:文本实体识别

java 复制代码
public static class TextAnalysis {
    private String summary;           // 摘要
    private String[] keywords;        // 关键词
    private String sentiment;         // 情感
    private Entities entities;        // 实体识别
    
    public static class Entities {
        private String[] persons;      // 人物
        private String[] locations;    // 地点
        private String[] organizations; // 组织
        // getters/setters...
    }
}

ReactAgent agent = ReactAgent.builder()
    .name("text_analyzer")
    .model(chatModel)
    .outputType(TextAnalysis.class)
    .build();

AssistantMessage result = agent.call(
    "分析:昨天,李明在北京参加了阿里巴巴公司的技术大会"
);

// 输出示例:
// {
//   "summary": "李明在北京参加阿里巴巴技术大会",
//   "keywords": ["李明", "北京", "阿里巴巴", "技术大会"],
//   "sentiment": "正面",
//   "entities": {
//     "persons": ["李明"],
//     "locations": ["北京"],
//     "organizations": ["阿里巴巴"]
//   }
// }

步骤四:原理解析

Spring AI Alibaba根据模型能力,自动选择最佳实现策略:

策略一:模型原生结构化输出

当使用DashScope、OpenAI等支持原生结构化输出的模型时,框架会自动启用模型的JSON模式:

  • DashScope:自动设置response_format: {"type": "json_object"}
  • OpenAI:使用API层面的JSON模式,严格保证格式正确

同时,框架会增强用户消息,追加格式指令:

java 复制代码
// 框架自动在UserMessage末尾追加Schema指令
messages.set(i, userMessage.mutate()
    .text(originalText + System.lineSeparator() + outputSchema)
    .build());

策略二:ToolCall结构化输出

对于不支持原生结构化输出的模型,框架通过动态ToolCall来实现格式化------利用所有现代模型都支持的工具调用能力,构造一个"格式化工具"来规整输出。

优势:适用于大多数模型,兼容性强

步骤五:错误处理

模型可能不总是返回完美的JSON,以下三种策略帮你从容应对:

[1]Try-Catch模式

java 复制代码
try {
    AssistantMessage result = agent.call("提取数据");
    ObjectMapper mapper = new ObjectMapper();
    DataOutput data = mapper.readValue(result.getText(), DataOutput.class);
    // 处理数据
} catch (JsonProcessingException e) {
    System.err.println("JSON解析失败: " + e.getMessage());
    System.err.println("原始输出: " + result.getText());
    // 降级处理:使用默认值或重新请求
}

[2]验证模式

在POJO中添加校验逻辑,确保数据有效性:

java 复制代码
public static class ValidatedOutput {
    private String title;
    private Integer rating;
    
    public void validate() throws IllegalArgumentException {
        if (title == null || title.isEmpty()) {
            throw new IllegalArgumentException("标题不能为空");
        }
        if (rating != null && (rating < 1 || rating > 5)) {
            throw new IllegalArgumentException("评分必须在1-5之间");
        }
    }
}

// 使用
ValidatedOutput output = mapper.readValue(result.getText(), ValidatedOutput.class);
output.validate();  // 自动校验

[3]重试模式

java 复制代码
int maxRetries = 3;
DataOutput data = null;

for (int i = 0; i < maxRetries; i++) {
    try {
        AssistantMessage result = agent.call("提取数据");
        data = mapper.readValue(result.getText(), DataOutput.class);
        break;
    } catch (Exception e) {
        if (i == maxRetries - 1) throw new RuntimeException("多次失败", e);
        System.out.println("第" + (i + 1) + "次失败,重试中...");
        Thread.sleep(1000);  // 等待后重试
    }
}

步骤六:实践总结

实践 说明
优先使用outputType 类型安全、代码简洁,框架自动处理Schema生成
POJO设计要合理 字段命名清晰,类型明确(String、数组等)
必须提供getter/setter Jackson反序列化依赖标准Java Bean规范
添加校验逻辑 在POJO中实现validate()方法,防御性编程
使用模型原生能力 DashScope/OpenAI等模型的JSON模式更稳定可靠
做好降级处理 即使结构化输出也有失败可能,始终准备Plan B

加入技术群可以获取资料,含AI资料、Spring AI中文文档等,等你加入~

相关推荐
Coremail邮件安全3 小时前
邮安实战,攻防有道|2026教育邮件安全实战闭门会在成都举行
人工智能
ECT-OS-JiuHuaShan3 小时前
整体论体系定理,全球开放,无法绕过
人工智能·科技·学习·算法·生活
云智慧AIOps社区3 小时前
云智慧亮相第二十八届智能体驱动的GOPS全球运维大会2026 · 深圳站!以运维智能体 Castrel AI (SRE Agent)保障系统稳定可靠!
运维·人工智能·ai agent·运维自动化·sre 智能体
Raink老师3 小时前
【AI面试临阵磨枪-27】CoT、ToT、Plan-and-Solve、Plan-and-Execute 分别是什么?适用场景?
人工智能·ai 面试
两年半的个人练习生^_^3 小时前
PinYin4j汉字转拼音使用及踩坑
java
无我Code3 小时前
全套开源:一款云端服务+本地设备计算的文生图应用
前端·人工智能·后端
chaofan9803 小时前
GPT-5.5 全压力测试:为什么 API 聚合调度是解决“首字延迟”的技术关键?
开发语言·人工智能·python·gpt·自动化·api
LcGero3 小时前
移动端AI OCR模型选型
人工智能·ai·ocr
人工智能AI技术3 小时前
智能体陷阱:过度自动化、稳定性、可靠性问题
人工智能