Spring AI Alibaba 与 AI 集成
定位说明
Spring Cloud Alibaba AI(以下简称 SCA AI)是 Spring AI 框架的阿里云实现,旨在让 AI 能力成为微服务体系的一等公民——AI 服务同样享受 Nacos 服务发现、Sentinel 流量控制、Seata 分布式事务等基础设施能力。
SCA AI 基于 Spring AI 抽象层(ChatClient、EmbeddingClient、ImageClient 等接口),底层接入阿里云通义系列大模型,使开发者可以用统一的 Spring 编程模型调用多种 AI 能力。
前置知识:读者应具备 Spring Boot 基础,了解大模型基本概念(Prompt / Token / Embedding / RAG)。本教程以 Spring Cloud Alibaba 2025.1.x + Spring Boot 4.0.x + JDK 17+ 为基础。
核心能力矩阵
SCA AI 覆盖通义大模型体系的六大能力域:
| 能力 | 说明 | 底层模型 |
|---|---|---|
| 对话(Chat) | 多轮对话,支持同步/流式/函数调用 | 通义千问全系列(qwen-max/turbo/plus) |
| 文生图(Image Generation) | 文本描述生成图片 | 通义万相 |
| 文生语音(TTS) | 文本转语音,支持多种音色 | CosyVoice |
| 语音转录(STT) | 语音转文本 | Paraformer |
| 向量嵌入(Embedding) | 文本向量化,支持中文优化 | text-embedding-v3 |
| 模型路由(Model Router) | 动态切换模型、负载均衡 | 内置策略引擎 |
环境准备
Maven 依赖
<!-- Spring AI Alibaba BOM(推荐通过 BOM 统一版本) -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2025.1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring AI BOM -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0-M6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Chat 对话能力 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-ai</artifactId>
</dependency>
</dependencies>
注意:Spring AI 1.0 正式版发布前,版本号遵循里程碑规则。实际开发时以 Maven 仓库最新版为准。
配置文件
spring:
ai:
tongyi:
api-key: ${DASHSCOPE_API_KEY} # 从阿里云百炼平台获取
chat:
enabled: true
model: qwen-max # 默认模型
options:
temperature: 0.7 # 创造性(0-1)
max-tokens: 2048 # 最大输出 token 数
top-p: 0.8 # 核采样
image:
enabled: true
model: wanx-v1
embedding:
enabled: true
model: text-embedding-v3
安全提醒:
api-key严禁硬编码在源代码中,生产环境必须通过环境变量或配置中心注入。
核心功能详解
一、对话(Chat)
对话能力是最基础也最常用的 AI 能力。SCA AI 提供两套编程模型:自动装配的 ChatClient 和 TongYiChatModel,推荐使用前者。
1.1 基础对话
@RestController
@RequestMapping("/ai")
public class ChatController {
private final ChatClient chatClient;
// 构造器注入(Spring AI 1.0 M6+ 推荐方式)
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping("/chat")
public String chat(@RequestParam(defaultValue = "用三句话介绍 Spring Cloud Alibaba") String prompt) {
return chatClient.prompt()
.user(prompt)
.call()
.content();
}
}
1.2 流式对话(SSE)
对于长文本生成场景,流式输出可以显著改善用户体验:
@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chatStream(@RequestParam String prompt) {
return chatClient.prompt()
.user(prompt)
.stream()
.content();
}
前端用 EventSource 接收 SSE 事件流,每次 onmessage 时会收到一段增量文本。
1.3 函数调用(Function Calling)
函数调用让大模型能够调用外部 API 获取实时数据,典型场景包括天气查询、数据库查询、RESTful API 调用等。
步骤一:定义函数
@Component
@Description("查询指定城市的实时天气信息")
public class WeatherFunction implements Function<WeatherFunction.Request, WeatherFunction.Response> {
public record Request(@JsonProperty(required = true)
@JsonPropertyDescription("城市名称,例如杭州、北京")
String city) {}
public record Response(String city, String weather, String temperature) {}
@Override
public Response apply(Request request) {
// 实际场景中调用天气 API
return new Response(request.city, "晴", "25°C");
}
}
步骤二:注册并调用
@GetMapping("/chat/weather")
public String weatherChat(@RequestParam String question) {
return chatClient.prompt()
.user(question)
.functions("weatherFunction") // 注册函数 bean 名称
.call()
.content();
}
调用示例:/chat/weather?question=杭州今天天气怎么样? → 大模型自动决定调用 weatherFunction,结合返回结果给出自然语言回答。
1.4 系统提示词(System Prompt)
通过 System Prompt 定制模型角色和行为:
chatClient.prompt()
.system("你是一名 Spring Cloud Alibaba 技术专家,回答必须包含代码示例。")
.user("如何配置 Nacos 集群?")
.call()
.content();
1.5 多轮对话
通过 Prompt 传递历史消息实现上下文记忆:
List<Message> history = new ArrayList<>();
history.add(new SystemMessage("你是客服助手"));
history.add(new UserMessage("我想退货"));
history.add(new AssistantMessage("请问订单号是多少?"));
history.add(new UserMessage("ORD123456"));
Prompt prompt = new Prompt(history);
String reply = chatClient.prompt(prompt).call().content();
二、文生图(Image Generation)
spring:
ai:
tongyi:
image:
enabled: true
model: wanx-v1
@RestController
@RequestMapping("/ai/image")
public class ImageController {
private final TongYiImageModel imageModel;
public ImageController(TongYiImageModel imageModel) {
this.imageModel = imageModel;
}
@GetMapping("/generate")
public String generateImage(@RequestParam String prompt) {
ImagePrompt imagePrompt = new ImagePrompt(prompt);
ImageResponse response = imageModel.call(imagePrompt);
// 返回图片 URL
return response.getResult().getOutput().getUrl();
}
}
三、文本转语音(TTS)
@RestController
@RequestMapping("/ai/tts")
public class TTSController {
private final TongYiAudioSpeechModel speechModel;
public TTSController(TongYiAudioSpeechModel speechModel) {
this.speechModel = speechModel;
}
@GetMapping(value = "/speak", produces = "audio/mpeg")
public byte[] speak(@RequestParam String text) {
SpeechPrompt prompt = new SpeechPrompt(text);
SpeechResponse response = speechModel.call(prompt);
return response.getResult().getOutput(); // 返回音频字节流
}
}
四、语音转录(STT)
@RestController
@RequestMapping("/ai/stt")
public class STTController {
private final TongYiAudioTranscriptionModel transcriptionModel;
public STTController(TongYiAudioTranscriptionModel transcriptionModel) {
this.transcriptionModel = transcriptionModel;
}
@PostMapping("/transcribe")
public String transcribe(@RequestParam("file") MultipartFile file) throws IOException {
AudioTranscriptionPrompt prompt = new AudioTranscriptionPrompt(
new ByteArrayResource(file.getBytes()));
AudioTranscriptionResponse response = transcriptionModel.call(prompt);
return response.getResult().getOutput();
}
}
五、向量嵌入(Embedding)
Embedding 是 RAG(检索增强生成)的基础,用于将文本转化为语义向量。
@RestController
@RequestMapping("/ai/embedding")
public class EmbeddingController {
private final TongYiEmbeddingModel embeddingModel;
public EmbeddingController(TongYiEmbeddingModel embeddingModel) {
this.embeddingModel = embeddingModel;
}
@GetMapping("/embed")
public List<Double> embed(@RequestParam String text) {
EmbeddingResponse response = embeddingModel.call(
new EmbeddingRequest(List.of(text), null));
return response.getResult().getOutput();
}
@GetMapping("/similarity")
public double similarity(@RequestParam String text1, @RequestParam String text2) {
List<Double> vec1 = embed(text1);
List<Double> vec2 = embed(text2);
// 余弦相似度
return cosineSimilarity(vec1, vec2);
}
}
六、RAG 检索增强生成
RAG(Retrieval-Augmented Generation)通过将外部知识库向量化后检索,使大模型能够回答超出训练数据的专业问题。
@RestController
@RequestMapping("/ai/rag")
public class RAGController {
private final VectorStore vectorStore; // 向量数据库(如阿里云 Elasticsearch / Milvus)
private final ChatClient chatClient;
public RAGController(VectorStore vectorStore, ChatClient.Builder builder) {
this.vectorStore = vectorStore;
this.chatClient = builder.build();
}
@GetMapping("/ask")
public String ask(@RequestParam String question) {
// 1. 从向量数据库检索相关文档
List<Document> docs = vectorStore.similaritySearch(
SearchRequest.query(question).withTopK(3));
// 2. 拼接上下文
String context = docs.stream()
.map(Document::getContent)
.collect(Collectors.joining("\n\n"));
// 3. 将上下文注入 Prompt 并调用大模型
return chatClient.prompt()
.system("基于以下参考资料回答问题,不要编造信息:\n\n" + context)
.user(question)
.call()
.content();
}
}
生态整合:AI 即微服务
SCA AI 的核心设计哲学是让 AI 服务享受微服务基础设施的全部红利:
| 整合能力 | 实践场景 |
|---|---|
| Nacos 服务发现 | AI 服务注册到 Nacos,Consumer 通过服务名调用 |
| Nacos 配置中心 | API Key、模型参数等敏感配置托管到 Nacos,支持动态切换 |
| Sentinel 流量控制 | 对 AI 接口限流(QPS 阈值/并发线程数),防止 API 费用暴涨 |
| Sentinel 熔断降级 | AI 服务超时或异常时熔断,返回兜底文案 |
| Seata 分布式事务 | 跨 AI + 数据库的业务操作(如"生成文案 + 存入数据库") |
面试考点
1. Spring AI 的抽象层次是怎样的?
Spring AI 定义了一套与具体大模型厂商无关的接口抽象(ChatClient / EmbeddingClient / ImageClient 等),每家厂商提供对应的实现。SCA AI 即为阿里通义系列的 Spring AI 实现。切换模型只需换 Starter 依赖和配置,业务代码无需改动。
2. Function Calling 的工作原理?
大模型在推理时判断用户意图是否需要调用外部函数。若需要,模型返回函数名和参数 JSON;应用层执行函数并返回结果给模型;模型基于结果生成最终的自然语言回复。整个过程基于 @Description 注解声明的函数描述进行语义匹配。
3. RAG 相比微调(Fine-Tuning)的优势?
| 维度 | RAG | 微调 |
|---|---|---|
| 知识更新 | 实时更新向量库即可 | 需重新训练 |
| 成本 | 低(仅检索 + 推理) | 高(GPU 训练) |
| 幻觉控制 | 引用来源可追溯 | 无法追溯 |
| 适用场景 | 知识库问答、文档检索 | 风格定制、专业术语习惯 |
4. 如何在生产环境安全地管理 AI API Key?
- 禁止硬编码:使用环境变量、Nacos Config 或 Vault
- 最小权限:为不同服务分配不同的 API Key,按需授权
- 费用控制:通过 Sentinel 限流限制调用频率,配合阿里云百炼平台的 QPS 配额
5. 流式输出与普通输出的适用场景?
| 维度 | 流式输出(Stream) | 普通输出(Call) |
|---|---|---|
| 响应方式 | SSE 逐段推送 | 一次性返回 |
| 用户体验 | 实时感强,适合长文本 | 等待感明显 |
| 适用场景 | 对话、文章生成 | API 调用、结构化提取 |
| 技术难度 | 需前后端 SSE 配合 | 简单 |
参考资源:
- Spring AI 官方文档:https://spring.io/projects/spring-ai
- 阿里云百炼平台:https://bailian.console.aliyun.com
- 通义千问模型列表:https://help.aliyun.com/document_detail/2712195.html