Spring Alibaba AI 实战指南:构建企业级智能应用
摘要
Spring Alibaba AI 是阿里巴巴开源的 Spring AI 实现,为开发者提供了统一的 API 来集成各种大语言模型(LLM)服务。本文将深入探讨 Spring Alibaba AI 的核心特性、架构设计和实战应用,帮助开发者快速构建企业级智能应用。
目录
- Spring Alibaba AI 简介
- 核心架构与设计理念
- 快速开始
- 核心功能详解
- 生产环境最佳实践
- 与开源框架集成
- 常见问题与解决方案
- 总结与展望
1. Spring Alibaba AI 简介
1.1 什么是 Spring Alibaba AI
Spring Alibaba AI 是基于 Spring AI 框架的阿里云通义千问模型实现,提供了简洁、统一的 API 接口,让开发者能够轻松地将 AI 能力集成到 Spring Boot 应用中。
核心优势:
- 统一的编程模型,降低学习成本
- 开箱即用的 Spring Boot Starter
- 支持流式响应和函数调用
- 完善的错误处理和重试机制
- 与 Spring 生态无缝集成
1.2 应用场景
┌─────────────────────────────────────────────────────────┐
│ Spring Alibaba AI 应用场景 │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 智能客服 │ │ 内容生成 │ │ 代码助手 │ │
│ │ │ │ │ │ │ │
│ │ • 问答系统 │ │ • 文章写作 │ │ • 代码生成 │ │
│ │ • 意图识别 │ │ • 文案优化 │ │ • Bug修复 │ │
│ │ • 多轮对话 │ │ • 翻译服务 │ │ • 代码审查 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 数据分析 │ │ 知识库问答 │ │ 文档理解 │ │
│ │ │ │ │ │ │ │
│ │ • 报表生成 │ │ • RAG应用 │ │ • 文档摘要 │ │
│ │ • 趋势预测 │ │ • 企业知识库 │ │ • 信息提取 │ │
│ │ • 异常检测 │ │ • 智能搜索 │ │ • 结构化输出 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
2. 核心架构与设计理念
2.1 整体架构
java
┌────────────────────────────────────────────────────────────┐
│ Spring Boot Application │
├────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Application Layer (Controller) │ │
│ └──────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌──────────────▼───────────────────────────────────────┐ │
│ │ Service Layer (Business Logic) │ │
│ └──────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌──────────────▼───────────────────────────────────────┐ │
│ │ Spring AI Abstraction Layer │ │
│ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │
│ │ │ ChatClient │ │ Prompt │ │ Function │ │ │
│ │ │ │ │ Template │ │ Calling │ │ │
│ │ └────────────┘ └────────────┘ └────────────┘ │ │
│ └──────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌──────────────▼───────────────────────────────────────┐ │
│ │ Spring Alibaba AI Implementation │ │
│ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │
│ │ │ ChatModel │ │ Embedding │ │ Image │ │ │
│ │ │ │ │ Model │ │ Model │ │ │
│ │ └────────────┘ └────────────┘ └────────────┘ │ │
│ └──────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌──────────────▼───────────────────────────────────────┐ │
│ │ Alibaba Cloud Tongyi API │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────┘
2.2 核心组件
ChatClient: 提供流畅的 API 接口用于构建对话请求
ChatModel: 对话模型的抽象接口
Prompt: 提示词管理和模板化
StreamingChatModel: 支持流式响应的模型接口
FunctionCallback: 函数调用能力,让 AI 能够调用外部工具
3. 快速开始
3.1 环境准备
前置条件:
- JDK 17+
- Spring Boot 3.0+
- Maven 3.6+ 或 Gradle 7.5+
- 阿里云通义千问 API Key
3.2 添加依赖
Maven 配置:
xml
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Alibaba AI Starter -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-ai</artifactId>
<version>2023.0.1.0</version>
</dependency>
<!-- Spring Boot Starter Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2023.0.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3.3 配置文件
application.yml:
yaml
spring:
application:
name: spring-alibaba-ai-demo
cloud:
ai:
tongyi:
api-key: ${TONGYI_API_KEY:your-api-key-here}
chat:
options:
model: qwen-turbo
temperature: 0.7
max-tokens: 2000
top-p: 0.9
# 日志配置
logging:
level:
com.alibaba.cloud.ai: DEBUG
org.springframework.ai: DEBUG
3.4 第一个示例
简单的对话接口:
java
package com.example.ai.controller;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/chat")
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
@PostMapping("/simple")
public String simpleChat(@RequestBody String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
启动类:
java
package com.example.ai;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringAlibabaAiApplication {
public static void main(String[] args) {
SpringApplication.run(SpringAlibabaAiApplication.class, args);
}
}
测试请求:
bash
curl -X POST http://localhost:8080/api/chat/simple \
-H "Content-Type: application/json" \
-d "介绍一下Spring Boot的核心特性"
4. 核心功能详解
4.1 基础对话功能
4.1.1 同步对话
java
package com.example.ai.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ChatService {
private final ChatClient chatClient;
private final ChatModel chatModel;
public ChatService(ChatClient.Builder chatClientBuilder, ChatModel chatModel) {
this.chatClient = chatClientBuilder.build();
this.chatModel = chatModel;
}
/**
* 基础对话 - 使用 ChatClient
*/
public String chat(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.content();
}
/**
* 带系统提示的对话
*/
public String chatWithSystem(String systemPrompt, String userMessage) {
return chatClient.prompt()
.system(systemPrompt)
.user(userMessage)
.call()
.content();
}
/**
* 使用 ChatModel 进行更底层的控制
*/
public String chatWithModel(String userMessage) {
Message message = new UserMessage(userMessage);
Prompt prompt = new Prompt(List.of(message));
return chatModel.call(prompt).getResult().getOutput().getContent();
}
/**
* 多轮对话
*/
public String multiTurnChat(List<Message> conversationHistory, String newMessage) {
conversationHistory.add(new UserMessage(newMessage));
Prompt prompt = new Prompt(conversationHistory);
return chatModel.call(prompt).getResult().getOutput().getContent();
}
}
4.1.2 流式响应
java
package com.example.ai.controller;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
@RestController
@RequestMapping("/api/stream")
public class StreamChatController {
private final ChatClient chatClient;
public StreamChatController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
/**
* SSE 流式响应
*/
@GetMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamChat(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.stream()
.content();
}
/**
* 带系统提示的流式响应
*/
@PostMapping(value = "/chat-with-context", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamChatWithContext(
@RequestParam String systemPrompt,
@RequestParam String userMessage) {
return chatClient.prompt()
.system(systemPrompt)
.user(userMessage)
.stream()
.content();
}
}
前端接收 SSE 示例(JavaScript):
javascript
const eventSource = new EventSource('/api/stream/chat?message=讲一个故事');
eventSource.onmessage = function(event) {
console.log('Received:', event.data);
document.getElementById('output').textContent += event.data;
};
eventSource.onerror = function(error) {
console.error('Error:', error);
eventSource.close();
};
4.2 提示词工程
4.2.1 提示词模板
java
package com.example.ai.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class PromptService {
private final ChatClient chatClient;
public PromptService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
/**
* 使用提示词模板生成代码审查报告
*/
public String reviewCode(String code, String language) {
String template = """
你是一位资深的代码审查专家。请对以下 {language} 代码进行详细审查:
代码:
```{language}
{code}
```
请从以下维度进行审查:
1. 代码质量和可读性
2. 潜在的 Bug 和安全漏洞
3. 性能优化建议
4. 最佳实践和设计模式
请以 Markdown 格式输出审查报告。
""";
PromptTemplate promptTemplate = new PromptTemplate(template);
Map<String, Object> params = Map.of(
"code", code,
"language", language
);
return chatClient.prompt()
.user(u -> u.text(promptTemplate.render(params)))
.call()
.content();
}
/**
* 文档生成模板
*/
public String generateDocumentation(String className, String methodSignature, String methodBody) {
String template = """
请为以下 Java 方法生成详细的 JavaDoc 文档:
类名: {className}
方法签名: {methodSignature}
方法体:
```java
{methodBody}
```
要求:
1. 包含方法描述
2. 详细说明所有参数
3. 说明返回值
4. 列出可能抛出的异常
5. 添加使用示例
请使用标准的 JavaDoc 格式。
""";
PromptTemplate promptTemplate = new PromptTemplate(template);
Map<String, Object> params = Map.of(
"className", className,
"methodSignature", methodSignature,
"methodBody", methodBody
);
return chatClient.prompt()
.user(u -> u.text(promptTemplate.render(params)))
.call()
.content();
}
/**
* SQL 查询生成
*/
public String generateSqlQuery(String tableSchema, String requirement) {
String template = """
根据以下数据库表结构和需求,生成优化的 SQL 查询:
表结构:
{tableSchema}
查询需求:
{requirement}
要求:
1. 生成高效的 SQL 查询语句
2. 包含必要的索引建议
3. 添加查询解释和注释
4. 考虑性能优化
""";
PromptTemplate promptTemplate = new PromptTemplate(template);
Map<String, Object> params = Map.of(
"tableSchema", tableSchema,
"requirement", requirement
);
return chatClient.prompt()
.user(u -> u.text(promptTemplate.render(params)))
.call()
.content();
}
}
4.3 函数调用(Function Calling)
函数调用是 Spring Alibaba AI 的强大特性,允许 AI 模型调用外部工具和服务。
4.3.1 定义函数
java
package com.example.ai.function;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import java.util.function.Function;
/**
* 天气查询函数
*/
public class WeatherFunction implements Function<WeatherFunction.Request, WeatherFunction.Response> {
public record Request(
@JsonProperty(required = true, value = "location")
@JsonPropertyDescription("城市名称,例如:北京、上海")
String location,
@JsonProperty(required = false, value = "unit")
@JsonPropertyDescription("温度单位:celsius(摄氏度) 或 fahrenheit(华氏度)")
String unit
) {}
public record Response(
String location,
double temperature,
String unit,
String condition,
int humidity,
String forecast
) {}
@Override
public Response apply(Request request) {
// 模拟调用天气 API
// 实际生产环境中,这里应该调用真实的天气服务
String location = request.location();
String unit = request.unit() != null ? request.unit() : "celsius";
// 模拟数据
double temperature = 22.5;
String condition = "晴天";
int humidity = 65;
String forecast = "未来三天多云转晴";
return new Response(location, temperature, unit, condition, humidity, forecast);
}
}
4.3.2 注册和使用函数
java
package com.example.ai.config;
import com.example.ai.function.WeatherFunction;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;
import java.util.function.Function;
@Configuration
public class FunctionConfig {
@Bean
@Description("获取指定城市的天气信息")
public Function<WeatherFunction.Request, WeatherFunction.Response> weatherFunction() {
return new WeatherFunction();
}
}
java
package com.example.ai.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.stereotype.Service;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
@Service
public class FunctionCallingService {
private final ChatClient chatClient;
public FunctionCallingService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder
.defaultFunctions("weatherFunction") // 注册默认函数
.build();
}
/**
* 使用函数调用回答问题
*/
public String chatWithFunction(String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
/**
* 带会话记忆的函数调用
*/
public String chatWithFunctionAndMemory(String conversationId, String message) {
return chatClient.prompt()
.user(message)
.advisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory()))
.advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, conversationId))
.call()
.content();
}
}
4.3.3 复杂函数示例 - 数据库查询
java
package com.example.ai.function;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
/**
* 数据库查询函数
*/
@Component
public class DatabaseQueryFunction implements Function<DatabaseQueryFunction.Request, DatabaseQueryFunction.Response> {
private final JdbcTemplate jdbcTemplate;
public DatabaseQueryFunction(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public record Request(
@JsonProperty(required = true, value = "query")
@JsonPropertyDescription("自然语言查询需求")
String query,
@JsonProperty(required = false, value = "limit")
@JsonPropertyDescription("返回结果数量限制")
Integer limit
) {}
public record Response(
String sql,
List<Map<String, Object>> results,
int rowCount,
String message
) {}
@Override
public Response apply(Request request) {
try {
// 实际应用中,这里应该将自然语言转换为 SQL
// 这里简化处理,假设已经有了 SQL
String sql = convertToSql(request.query());
int limit = request.limit() != null ? request.limit() : 10;
sql = sql + " LIMIT " + limit;
List<Map<String, Object>> results = jdbcTemplate.queryForList(sql);
return new Response(
sql,
results,
results.size(),
"查询成功"
);
} catch (Exception e) {
return new Response(
"",
List.of(),
0,
"查询失败: " + e.getMessage()
);
}
}
private String convertToSql(String naturalLanguageQuery) {
// 简化示例:实际应该使用 AI 来转换
// 这里仅作演示
return "SELECT * FROM users WHERE 1=1";
}
}
4.4 RAG (检索增强生成)
RAG 是构建企业级知识库问答系统的核心技术。
4.4.1 文档向量化
java
package com.example.ai.service;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.TextReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class DocumentService {
private final VectorStore vectorStore;
private final TokenTextSplitter textSplitter;
public DocumentService(VectorStore vectorStore) {
this.vectorStore = vectorStore;
// 配置文本分割器:每个块 500 个 token,重叠 100 个 token
this.textSplitter = new TokenTextSplitter(500, 100);
}
/**
* 将文档添加到向量数据库
*/
public void addDocument(Resource resource) {
// 读取文档
TextReader textReader = new TextReader(resource);
List<Document> documents = textReader.get();
// 分割文档
List<Document> chunks = textSplitter.apply(documents);
// 存储到向量数据库
vectorStore.add(chunks);
}
/**
* 批量添加文档
*/
public void addDocuments(List<Resource> resources) {
resources.forEach(this::addDocument);
}
/**
* 搜索相关文档
*/
public List<Document> searchSimilarDocuments(String query, int topK) {
return vectorStore.similaritySearch(query, topK);
}
}
4.4.2 RAG 问答服务
java
package com.example.ai.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;
@Service
public class RagService {
private final ChatClient chatClient;
private final VectorStore vectorStore;
public RagService(ChatClient.Builder chatClientBuilder, VectorStore vectorStore) {
this.vectorStore = vectorStore;
this.chatClient = chatClientBuilder.build();
}
/**
* 基于知识库的问答
*/
public String askQuestion(String question) {
return chatClient.prompt()
.user(question)
.advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
.call()
.content();
}
/**
* 自定义检索策略的问答
*/
public String askQuestionWithCustomSearch(String question, int topK, double similarityThreshold) {
SearchRequest searchRequest = SearchRequest.defaults()
.withTopK(topK)
.withSimilarityThreshold(similarityThreshold);
return chatClient.prompt()
.user(question)
.advisors(new QuestionAnswerAdvisor(vectorStore, searchRequest))
.call()
.content();
}
/**
* 带引用来源的问答
*/
public String askQuestionWithSources(String question) {
String systemPrompt = """
你是一个专业的知识库助手。在回答问题时:
1. 基于提供的上下文信息准确回答
2. 如果信息不足,明确说明
3. 在回答末尾列出引用的文档来源
""";
return chatClient.prompt()
.system(systemPrompt)
.user(question)
.advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
.call()
.content();
}
}
5. 生产环境最佳实践
5.1 错误处理与重试
java
package com.example.ai.service;
import io.github.resilience4j.retry.Retry;
import io.github.resilience4j.retry.RetryConfig;
import io.github.resilience4j.retry.RetryRegistry;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.retry.NonTransientAiException;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.function.Supplier;
@Service
public class ResilientChatService {
private final ChatClient chatClient;
private final Retry retry;
public ResilientChatService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
// 配置重试策略
RetryConfig config = RetryConfig.custom()
.maxAttempts(3)
.waitDuration(Duration.ofSeconds(2))
.retryExceptions(Exception.class)
.ignoreExceptions(NonTransientAiException.class)
.build();
RetryRegistry registry = RetryRegistry.of(config);
this.retry = registry.retry("chatService");
}
/**
* 带重试机制的对话
*/
public String chatWithRetry(String message) {
Supplier<String> supplier = Retry.decorateSupplier(retry, () ->
chatClient.prompt()
.user(message)
.call()
.content()
);
return supplier.get();
}
}
5.2 响应缓存
java
package com.example.ai.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class CachedChatService {
private final ChatClient chatClient;
public CachedChatService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
/**
* 缓存常见问题的回答
*/
@Cacheable(value = "chatResponses", key = "#message")
public String getCachedResponse(String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
缓存配置:
java
package com.example.ai.config;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("chatResponses");
cacheManager.setCaffeine(Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(1, TimeUnit.HOURS)
.recordStats());
return cacheManager;
}
}
5.3 限流与熔断
java
package com.example.ai.service;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import io.github.resilience4j.ratelimiter.RateLimiter;
import io.github.resilience4j.ratelimiter.RateLimiterConfig;
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.function.Supplier;
@Service
public class ProtectedChatService {
private final ChatClient chatClient;
private final RateLimiter rateLimiter;
private final CircuitBreaker circuitBreaker;
public ProtectedChatService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
// 限流配置:每秒最多 10 个请求
RateLimiterConfig rateLimiterConfig = RateLimiterConfig.custom()
.limitForPeriod(10)
.limitRefreshPeriod(Duration.ofSeconds(1))
.timeoutDuration(Duration.ofSeconds(5))
.build();
RateLimiterRegistry rateLimiterRegistry = RateLimiterRegistry.of(rateLimiterConfig);
this.rateLimiter = rateLimiterRegistry.rateLimiter("chatRateLimiter");
// 熔断器配置
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofMinutes(1))
.slidingWindowSize(10)
.build();
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(circuitBreakerConfig);
this.circuitBreaker = circuitBreakerRegistry.circuitBreaker("chatCircuitBreaker");
}
/**
* 带限流和熔断保护的对话
*/
public String protectedChat(String message) {
Supplier<String> supplier = () ->
chatClient.prompt()
.user(message)
.call()
.content();
// 应用限流
supplier = RateLimiter.decorateSupplier(rateLimiter, supplier);
// 应用熔断
supplier = CircuitBreaker.decorateSupplier(circuitBreaker, supplier);
return supplier.get();
}
}
5.4 日志与监控
java
package com.example.ai.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class ChatLoggingAspect {
private static final Logger logger = LoggerFactory.getLogger(ChatLoggingAspect.class);
@Around("execution(* com.example.ai.service.*ChatService.*(..))")
public Object logChatExecution(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
logger.info("开始执行 AI 对话方法: {}, 参数: {}", methodName, args);
long startTime = System.currentTimeMillis();
try {
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - startTime;
logger.info("AI 对话完成: {}, 耗时: {}ms", methodName, duration);
return result;
} catch (Exception e) {
long duration = System.currentTimeMillis() - startTime;
logger.error("AI 对话失败: {}, 耗时: {}ms, 错误: {}",
methodName, duration, e.getMessage(), e);
throw e;
}
}
}
6. 与开源框架集成
6.1 集成 LangChain4j
java
package com.example.ai.integration;
import dev.langchain4j.chain.ConversationalChain;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
/**
* LangChain4j 集成示例
* 注意:这是概念性示例,实际使用需要额外配置
*/
@Service
public class LangChain4jIntegrationService {
private final ChatClient chatClient;
public LangChain4jIntegrationService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
/**
* 使用 Spring AI 作为底层模型
*/
public String chatWithMemory(String conversationId, String message) {
// 使用 Spring AI 的会话管理
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
6.2 集成 Spring Cloud
java
package com.example.ai.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
/**
* Spring Cloud 集成配置
*/
@Configuration
public class CloudConfig {
/**
* 负载均衡的 WebClient
*/
@Bean
@LoadBalanced
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
java
package com.example.ai.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.stereotype.Service;
/**
* 集成 Spring Cloud Circuit Breaker
*/
@Service
public class CloudAwareChatService {
private final ChatClient chatClient;
private final CircuitBreakerFactory circuitBreakerFactory;
public CloudAwareChatService(
ChatClient.Builder chatClientBuilder,
CircuitBreakerFactory circuitBreakerFactory) {
this.chatClient = chatClientBuilder.build();
this.circuitBreakerFactory = circuitBreakerFactory;
}
public String chatWithCircuitBreaker(String message) {
return circuitBreakerFactory.create("chatService").run(
() -> chatClient.prompt()
.user(message)
.call()
.content(),
throwable -> "服务暂时不可用,请稍后重试"
);
}
}
6.3 集成 Spring Security
java
package com.example.ai.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/chat/**").authenticated()
.anyRequest().authenticated()
)
.oauth2Login(oauth2 -> oauth2
.defaultSuccessUrl("/dashboard", true)
);
return http.build();
}
}
java
package com.example.ai.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
/**
* 安全感知的聊天服务
*/
@Service
public class SecureChatService {
private final ChatClient chatClient;
public SecureChatService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
/**
* 带用户上下文的对话
*/
public String secureChat(String message) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();
String systemPrompt = String.format(
"你正在为用户 %s 提供服务。请记住用户身份,提供个性化的帮助。",
username
);
return chatClient.prompt()
.system(systemPrompt)
.user(message)
.call()
.content();
}
}
7. 常见问题与解决方案
7.1 API 限流问题
问题描述: 频繁调用 AI 接口导致触发限流。
解决方案:
java
package com.example.ai.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
@Service
public class ThrottledChatService {
private final ChatClient chatClient;
private final Semaphore semaphore;
private final ExecutorService executorService;
public ThrottledChatService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
// 限制并发请求数为 5
this.semaphore = new Semaphore(5);
this.executorService = Executors.newFixedThreadPool(10);
}
/**
* 限流的异步对话
*/
public CompletableFuture<String> asyncChatWithThrottle(String message) {
return CompletableFuture.supplyAsync(() -> {
try {
semaphore.acquire();
return chatClient.prompt()
.user(message)
.call()
.content();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("请求被中断", e);
} finally {
semaphore.release();
}
}, executorService);
}
}
7.2 超时处理
java
package com.example.ai.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.concurrent.*;
@Service
public class TimeoutChatService {
private final ChatClient chatClient;
private final ExecutorService executorService;
public TimeoutChatService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
this.executorService = Executors.newCachedThreadPool();
}
/**
* 带超时的对话
*/
public String chatWithTimeout(String message, Duration timeout) {
Future<String> future = executorService.submit(() ->
chatClient.prompt()
.user(message)
.call()
.content()
);
try {
return future.get(timeout.toMillis(), TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
future.cancel(true);
throw new RuntimeException("请求超时", e);
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException("请求失败", e);
}
}
}
7.3 成本优化
java
package com.example.ai.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.metadata.Usage;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Service
public class CostAwareChatService {
private static final Logger logger = LoggerFactory.getLogger(CostAwareChatService.class);
private final ChatClient chatClient;
public CostAwareChatService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
/**
* 跟踪 Token 使用情况
*/
public String chatWithUsageTracking(String message) {
ChatResponse response = chatClient.prompt()
.user(message)
.call()
.chatResponse();
// 获取使用情况
Usage usage = response.getMetadata().getUsage();
logger.info("Token 使用情况 - 提示词: {}, 完成: {}, 总计: {}",
usage.getPromptTokens(),
usage.getGenerationTokens(),
usage.getTotalTokens());
return response.getResult().getOutput().getContent();
}
/**
* 使用更经济的模型
*/
public String economicalChat(String message) {
return chatClient.prompt()
.user(message)
.options(opts -> opts
.model("qwen-turbo") // 使用更经济的模型
.maxTokens(1000)) // 限制输出长度
.call()
.content();
}
}
8. 总结与展望
8.1 核心要点回顾
┌─────────────────────────────────────────────────────────┐
│ Spring Alibaba AI 核心特性总结 │
├─────────────────────────────────────────────────────────┤
│ │
│ 1. 统一 API │
│ └─ 简化 AI 集成,降低学习成本 │
│ │
│ 2. 流式响应 │
│ └─ 提升用户体验,实时显示生成内容 │
│ │
│ 3. 函数调用 │
│ └─ 扩展 AI 能力,集成外部工具和服务 │
│ │
│ 4. RAG 支持 │
│ └─ 构建企业知识库,提供准确的领域回答 │
│ │
│ 5. Spring 集成 │
│ └─ 无缝融入 Spring 生态系统 │
│ │
│ 6. 生产就绪 │
│ └─ 错误处理、重试、限流、监控完善 │
│ │
└─────────────────────────────────────────────────────────┘
8.2 最佳实践建议
- 提示词工程:投入时间优化提示词,可以显著提升回答质量
- 错误处理:实现完善的重试和降级机制
- 性能优化:使用缓存、限流、异步处理
- 成本控制:监控 Token 使用,选择合适的模型
- 安全性:验证输入输出,防止注入攻击
- 可观测性:添加日志、指标、链路追踪
8.3 未来发展方向
多模态能力:
- 图像理解与生成
- 语音识别与合成
- 视频分析
更强大的 Agent:
- 自主规划和执行
- 多 Agent 协作
- 长期记忆管理
企业级特性:
- 私有化部署支持
- 细粒度权限控制
- 审计和合规
8.4 参考资源
官方文档:
- Spring AI: docs.spring.io/spring-ai/r...
- Spring Alibaba: sca.aliyun.com/
- 通义千问: help.aliyun.com/zh/dashscop...
结语
Spring Alibaba AI 为 Java 开发者提供了强大而易用的 AI 集成能力。通过本文的介绍和示例,你应该能够:
- 理解 Spring Alibaba AI 的核心概念和架构
- 快速搭建基于 AI 的应用
- 掌握提示词工程、函数调用、RAG 等高级特性
- 应用生产环境的最佳实践
- 集成到现有的 Spring 应用中
AI 技术正在快速发展,Spring Alibaba AI 也在不断演进。建议持续关注官方文档和社区动态,探索更多可能性。