Spring AI Alibaba 格式化输出
Spring AI Alibaba 格式化输出
1. 概述
Spring AI Alibaba 是阿里云基于 Spring AI 生态打造的 AI 应用开发框架,为开发者提供了统一、简洁的 API 来调用阿里云的各类 AI 服务。格式化输出是大模型应用开发中的核心能力,它解决了大模型原生输出格式不固定、难以被程序解析的问题,是实现 AI 与业务系统无缝集成的关键。
Spring AI Alibaba 提供了多种强大的格式化输出能力,包括:
- 结构化输出(JSON/XML)
- 流式输出(SSE)
- Markdown 格式化输出
- 函数调用(Function Calling)输出
- 自定义格式转换器
本文档将深入剖析这些格式化输出技术的实现原理,并提供完整的可运行案例。
2. 环境准备
2.1 依赖配置
在 pom.xml 中添加以下依赖(以 Spring Boot 3.2.x 为例):
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2023.0.1.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring AI Alibaba 通义千问核心依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
<!-- Web 依赖(用于流式输出和接口测试) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Lombok(简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
2.2 配置文件
在 application.yml 中配置通义千问 API 密钥:
spring:
ai:
dashscope:
api-key: ${DASHSCOPE_API_KEY:你的API密钥}
chat:
options:
model: qwen-max
temperature: 0.1 # 格式化输出建议使用较低的温度值
注意:格式化输出对模型的确定性要求较高,建议将
temperature设置在 0.1-0.3 之间。
3. 结构化输出(JSON/XML)
3.1 知识点剖析
结构化输出是指让大模型按照指定的 schema 生成符合格式要求的 JSON 或 XML 数据。Spring AI Alibaba 实现结构化输出的核心原理是:
- Schema 自动生成:通过反射将 Java 类转换为 JSON Schema
- 提示词注入:自动将 Schema 信息添加到系统提示词中
- 输出解析:自动将模型返回的字符串解析为 Java 对象
- 容错处理:内置了多种容错机制,处理模型输出不严格符合格式的情况
Spring AI Alibaba 支持两种结构化输出方式:
- 基于
@StructuredOutput注解:简单易用,适合大多数场景 - 基于
StructuredOutputConverter接口:灵活强大,支持自定义格式
4. 流式输出(SSE)
4.1 知识点剖析
流式输出(Server-Sent Events, SSE)是指大模型在生成内容的过程中,将结果逐字逐句地返回给客户端。这种方式可以显著提升用户体验,特别是在生成长文本时。
Spring AI Alibaba 流式输出的核心特性:
- 基于 Flux 的响应式编程模型:支持背压和异步处理
- Token 级别的流式返回:可以实时展示模型生成的每个字
- 完整的事件类型支持:包括内容事件、完成事件和错误事件
- 与 Spring WebFlux 无缝集成:支持响应式 Web 应用
6. 函数调用(Function Calling)输出
6.1 知识点剖析
函数调用是指大模型根据用户的问题,自动决定是否调用外部工具/函数来获取信息,然后基于工具返回的结果生成最终回答。这是实现智能代理(Agent)的核心技术。
Spring AI Alibaba 函数调用的工作流程:
- 开发者定义函数并注册到 Spring 容器
- Spring AI 自动将函数转换为 JSON Schema 并发送给模型
- 模型根据用户问题判断是否需要调用函数
- 如果需要调用,模型返回函数调用指令
- Spring AI 自动执行对应的函数
- 将函数返回结果发送给模型
- 模型基于函数结果生成最终回答
6.2 案例:天气查询函数
步骤 1:定义函数参数和返回值
import lombok.Data;
@Data
public class WeatherRequest {
private String city;
private String date;
}
@Data
public class WeatherResponse {
private String city;
private String date;
private String weather;
private int temperature;
private int humidity;
private String wind;
}
步骤 2:实现函数
import org.springframework.ai.model.function.FunctionCallback;
import org.springframework.ai.model.function.FunctionCallbackWrapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.function.Function;
@Configuration
public class FunctionConfig {
@Bean
public FunctionCallback weatherFunction() {
return FunctionCallbackWrapper.builder(new WeatherFunction())
.withName("getWeather")
.withDescription("查询指定城市指定日期的天气信息")
.withInputType(WeatherRequest.class)
.build();
}
public static class WeatherFunction implements Function<WeatherRequest, WeatherResponse> {
@Override
public WeatherResponse apply(WeatherRequest request) {
// 这里模拟调用天气API
WeatherResponse response = new WeatherResponse();
response.setCity(request.getCity());
response.setDate(request.getDate());
response.setWeather("晴");
response.setTemperature(25);
response.setHumidity(60);
response.setWind("东北风 3级");
return response;
}
}
}
步骤 3:使用函数调用
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/weather")
public class WeatherController {
private final ChatClient chatClient;
public WeatherController(ChatModel chatModel) {
this.chatClient = ChatClient.create(chatModel);
}
@GetMapping("/query")
public String queryWeather(@RequestParam String question) {
return chatClient.prompt()
.user(question)
.functions("getWeather")
.call()
.content();
}
}
测试:访问 http://localhost:8080/api/weather/query?question=明天北京的天气怎么样
7. 最佳实践与常见问题
7.1 最佳实践
-
结构化输出最佳实践:
- 使用简单清晰的数据模型,避免过深的嵌套
- 为字段添加明确的注释,帮助模型理解字段含义
- 使用较低的
temperature值(0.1-0.3)提高输出稳定性 - 总是添加异常处理,应对模型输出不符合格式的情况
-
流式输出最佳实践:
- 使用
MediaType.TEXT_EVENT_STREAM_VALUE作为响应类型 - 在前端使用
EventSource处理 SSE 响应 - 添加超时处理和重连机制
- 对于长文本生成,考虑分段处理
- 使用
-
函数调用最佳实践:
- 函数名称和描述要清晰准确
- 函数参数要尽可能简单
- 限制函数调用的次数,避免无限循环
- 对函数返回结果进行验证和清洗
7.2 常见问题与解决方案
问题 1:结构化输出偶尔不符合 JSON 格式
解决方案:
- 降低
temperature值 - 在提示词中强调格式要求
- 使用更简单的数据模型
- 添加容错解析逻辑,例如使用
JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES
问题 2:流式输出在某些浏览器中不工作
解决方案:
- 确保服务器没有启用压缩
- 添加
Cache-Control: no-cache响应头 - 在前端使用 polyfill 支持旧浏览器
问题 3:函数调用总是不被触发
解决方案:
- 检查函数名称和描述是否清晰
- 确保函数参数类型正确
- 在提示词中明确说明可以使用哪些函数
- 尝试使用更明确的问题
8. 总结
Spring AI Alibaba 提供了全面而强大的格式化输出能力,极大地简化了 AI 应用的开发过程。通过本文档介绍的结构化输出、流式输出、Markdown 输出和函数调用技术,开发者可以快速构建出高质量、用户体验良好的 AI 应用。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)