1. Spring AI Alibaba 框架概述
Spring AI Alibaba 是阿里巴巴基于 Spring 生态推出的 AI 应用开发框架,它让 Java 开发者能够快速将 AI 能力集成到企业应用中。作为一个在 Java 生态深耕多年的开发者,我发现这个框架完美解决了传统 AI 集成中的几个痛点:
- 开发效率问题:通过熟悉的 Spring 注解和配置方式,开发者可以在 10 分钟内完成基础 AI 功能接入
- 工程化难题:提供了标准的记忆管理、工具调用、智能体编排等企业级特性
- 云原生适配:天然支持阿里云 DashScope 等云服务,同时保持架构中立性
提示:虽然框架支持多种 AI 模型,但在生产环境建议使用 DashScope 的 qwen-max 模型,它在中文场景下的表现最为稳定。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础对话功能实现
2.1 最简对话实现
让我们从一个最简单的聊天接口开始。这个示例展示了如何用 15 行代码实现 AI 对话功能:
java复制@RestController
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping("/chat")
public String chat(@RequestParam String query) {
return chatClient.prompt(query).call().content();
}
}
这段代码有几个关键点需要注意:
ChatClient.Builder是线程安全的,适合在 Spring 容器中单例使用prompt()方法支持链式调用,可以添加各种配置call()是阻塞式调用,适合简单场景
2.2 多轮对话实现
实际业务中,我们往往需要维护对话上下文。下面是带历史消息的多轮对话实现:
java复制List<Message> messages = List.of(
new SystemMessage("你是一个 Java 专家"),
new UserMessage("什么是 Spring Boot?"),
new AssistantMessage("Spring Boot 是..."),
new UserMessage("它有什么优势?")
);
Prompt prompt = new Prompt(messages);
ChatResponse response = chatModel.call(prompt);
消息类型说明:
SystemMessage:设定 AI 角色和行为准则UserMessage:用户输入内容AssistantMessage:AI 的历史回复
2.3 流式响应优化
对于需要长时间处理的请求,流式响应能显著提升用户体验:
java复制Flux<ChatResponse> responseStream = chatModel.stream(
new Prompt("解释 Spring Boot 自动配置")
);
responseStream.subscribe(chatResponse -> {
System.out.print(chatResponse.getResult().getOutput().getText());
});
注意:流式响应需要客户端支持 Server-Sent Events (SSE) 或 WebSocket。在 Spring Boot 中返回
Flux<String>类型会自动启用 SSE。
2.4 对话记忆管理
生产环境中,我们需要持久化对话记录。框架提供了开箱即用的记忆管理方案:
java复制@RestController
@RequestMapping("/advisor/memory")
public class ChatMemoryController {
private final ChatClient chatClient;
private final MessageWindowChatMemory chatMemory;
public ChatMemoryController(ChatClient.Builder builder, ChatMemoryRepository repository) {
this.chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(repository)
.maxMessages(100)
.build();
this.chatClient = builder
.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
.build();
}
@GetMapping("/call")
public String call(@RequestParam String query, @RequestParam String conversationId) {
return chatClient.prompt(query)
.advisors(a -> a.param(CONVERSATION_ID, conversationId))
.call().content();
}
}
关键配置项:
maxMessages:控制记忆窗口大小,避免内存溢出ChatMemoryRepository:支持 Redis、JDBC 等多种存储后端conversationId:通过该参数实现多会话隔离
3. ReactAgent 高级应用
3.1 基础配置
ReactAgent 是框架的核心抽象,代表一个具备工具使用能力的智能体:
java复制@Configuration
public class AgentConfiguration {
private final ChatModel chatModel;
@Bean
public ReactAgent reactAgent() throws GraphStateException {
return ReactAgent.builder()
.name("agent")
.description("This is a react agent")
.model(chatModel)
.saver(new MemorySaver())
.tools(
new FileReadTool().toolCallback(),
new FileWriteTool().toolCallback()
)
.hooks(HumanInTheLoopHook.builder()
.approvalOn("file_write", "Write File should be approved")
.build())
.interceptors(new LogToolInterceptor())
.build();
}
}
配置要点:
name和description会作为系统提示词的一部分MemorySaver确保智能体状态持久化HumanInTheLoopHook为危险操作添加人工审批层
3.2 自定义工具开发
工具是扩展智能体能力的关键。下面是一个安全的文件写入工具实现:
java复制@Component
public class FileWriteTool implements BiFunction<FileWriteTool.Request, ToolContext, String> {
@Override
public ToolCallback toolCallback() {
return FunctionToolCallback.builder("file_write", this)
.description("Tool for write files")
.inputType(Request.class)
.build();
}
@Override
public String apply(Request request, ToolContext toolContext) {
try {
// 安全路径处理
String safePath = Paths.get(System.getProperty("user.dir"))
.resolve(request.filePath).normalize().toString();
// 写入前校验父目录是否存在
Path parentDir = Paths.get(safePath).getParent();
if (!Files.exists(parentDir)) {
Files.createDirectories(parentDir);
}
Files.writeString(Paths.get(safePath), request.content);
return "Successfully wrote to file: " + request.filePath;
} catch (IOException e) {
return "Error writing to file: " + e.getMessage();
}
}
public record Request(
@JsonProperty(value = "file_path", required = true)
@JsonPropertyDescription("The path of the file to write")
String filePath,
@JsonProperty(value = "content", required = true)
@JsonPropertyDescription("The content to write to the file")
String content
) {}
}
工具开发最佳实践:
- 使用
normalize()防止路径遍历攻击 - 为每个工具定义清晰的输入模式(Request DTO)
- 提供详细的参数描述,帮助 LLM 正确使用工具
3.3 结构化输出控制
让 AI 返回结构化数据可以大幅简化后续处理:
java复制// 定义输出格式
public class ContactInfo {
@JsonProperty("name")
private String fullName;
@JsonProperty("email")
@Pattern(regexp = "^\\S+@\\S+\\.\\S+$")
private String emailAddress;
@JsonProperty("phone")
private String phoneNumber;
// 省略 getter/setter
}
// 配置结构化输出
ReactAgent agent = ReactAgent.builder()
.name("contact_extractor")
.model(chatModel)
.outputType(ContactInfo.class)
.build();
// 调用示例
AssistantMessage result = agent.call(
"提取联系人信息:张三,zhangsan@example.com,(555) 123-4567");
输出验证技巧:
- 使用 JSR-303 注解校验数据格式
- 通过
@JsonProperty控制 JSON 字段名 - 复杂结构可以配合 JSON Schema 进行描述
4. 多智能体协作模式
4.1 顺序执行管道
对于需要多步骤处理的任务,SequentialAgent 是理想选择:
java复制@Configuration
public class ResearchTeamConfig {
@Bean
public ReactAgent researcher(ChatModel model) {
return ReactAgent.builder()
.name("researcher")
.model(model)
.systemPrompt("你是一个研究专家,负责收集和整理信息。")
.tools(new WebSearchTool(), new DocumentReaderTool())
.build();
}
@Bean
public SequentialAgent researchPipeline(ReactAgent researcher,
ReactAgent analyst,
ReactAgent writer) {
return SequentialAgent.builder()
.name("research-pipeline")
.addAgent(researcher)
.addAgent(analyst)
.addAgent(writer)
.errorHandler((agent, input, error) -> {
// 自定义错误处理逻辑
return "处理失败: " + error.getMessage();
})
.build();
}
}
管道设计建议:
- 每个智能体保持单一职责
- 设置合理的超时时间(默认无超时)
- 实现自定义错误处理逻辑
4.2 并行执行优化
当子任务相互独立时,使用 ParallelAgent 提高效率:
java复制ParallelAgent parallel = ParallelAgent.builder()
.name("multi-research")
.addAgent(techResearchAgent)
.addAgent(marketResearchAgent)
.addAgent(competitorResearchAgent)
.timeout(Duration.ofSeconds(30)) // 设置全局超时
.aggregator(results -> {
// 自定义结果聚合逻辑
return results.stream()
.filter(Objects::nonNull)
.collect(Collectors.joining("\n\n---\n\n"));
})
.build();
性能调优技巧:
- 根据任务复杂度设置合适的线程池大小
- 为每个子任务设置独立超时
- 聚合逻辑应考虑部分失败的情况
4.3 动态路由实现
RoutingAgent 可以根据输入内容动态选择处理路径:
java复制RoutingAgent router = RoutingAgent.builder()
.name("support-router")
.router((input, agents) -> {
if (input.contains("技术")) {
return "tech-support";
} else if (input.contains("账单")) {
return "billing-support";
}
return "general-support";
})
.addAgent("tech-support", techAgent)
.addAgent("billing-support", billingAgent)
.addAgent("general-support", generalAgent)
.defaultAgent("general-support") // 设置默认路由
.build();
路由设计经验:
- 路由逻辑应该保持简单明确
- 总是设置默认路由兜底
- 可以通过训练数据优化路由准确性
5. RAG 应用实战
5.1 知识库构建
实现一个基于向量搜索的知识检索工具:
java复制@Component
public class KnowledgeRetrievalTool implements BiFunction<Request, ToolContext, String> {
private final SimpleVectorStore vectorStore;
public KnowledgeRetrievalTool(EmbeddingModel embeddingModel) {
this.vectorStore = SimpleVectorStore.builder(embeddingModel)
.distanceMetric(DistanceMetric.COSINE)
.build();
}
@PostConstruct
void initKnowledgeBase() {
// 文档预处理流水线
DocumentReader reader = new JsoupDocumentReader("https://java2ai.com/docs/");
TokenTextSplitter splitter = new TokenTextSplitter()
.setChunkSize(500)
.setChunkOverlap(50);
List<Document> documents = splitter.apply(reader.get());
vectorStore.add(documents);
}
@Override
public String apply(Request request, ToolContext toolContext) {
SearchRequest searchRequest = SearchRequest.builder()
.query(request.query())
.topK(request.topK() != null ? request.topK() : 4)
.build();
List<Document> documents = vectorStore.similaritySearch(searchRequest);
return documents.stream()
.map(doc -> "来源: " + doc.getMetadata().get("source") + "\n" +
"内容:\n" + doc.getFormattedContent())
.collect(Collectors.joining("\n\n---\n\n"));
}
}
知识库优化建议:
- 分块大小建议 500-1000 tokens
- 添加适当的重叠区域(50-100 tokens)
- 保留文档元数据方便溯源
5.2 RAG Agent 集成
将知识检索工具与智能体结合:
java复制@Configuration
public class RagAgentConfiguration {
@Bean
public ReactAgent ragAgent(ChatModel model, KnowledgeRetrievalTool knowledgeTool) {
return ReactAgent.builder()
.name("rag-agent")
.description("""
你是一个知识库问答助手,请遵循以下规则:
1. 首先使用知识检索工具获取相关信息
2. 根据检索结果回答问题
3. 明确标注信息出处""")
.model(model)
.tools(knowledgeTool.toolCallback())
.promptTemplate("""
基于以下上下文回答问题:
{context}
问题:{input}
答案:""")
.build();
}
}
提示词设计要点:
- 明确要求 AI 使用工具获取信息
- 规定答案的组织格式
- 强调信息溯源的重要性
6. 生产环境最佳实践
6.1 配置管理
推荐使用 Spring Cloud Alibaba 的配置中心管理 AI 参数:
yaml复制spring:
ai:
dashscope:
api-key: ${AI_DASHSCOPE_API_KEY}
chat:
options:
model: qwen-max
temperature: 0.7 # 控制创造性
top-p: 0.9 # 控制多样性
max-tokens: 2000 # 防止长文本溢出
关键参数说明:
temperature:值越高输出越随机(0.3-1.0)top-p:核采样阈值(0.5-1.0)max-tokens:根据业务场景调整
6.2 监控与治理
通过 Spring Boot Actuator 添加健康检查:
java复制@Configuration
public class AiHealthConfig {
@Bean
public HealthIndicator aiHealthIndicator(ChatModel chatModel) {
return () -> {
try {
String response = chatModel.call("你好").getResult().getOutput().getText();
return Health.up()
.withDetail("response", response.substring(0, 20) + "...")
.build();
} catch (Exception e) {
return Health.down(e).build();
}
};
}
}
监控建议:
- 记录每次调用的耗时和 token 使用量
- 设置 QPS 限流防止超额收费
- 实现熔断机制应对服务不可用
6.3 安全防护
重要安全措施清单:
- 对所有工具调用实施权限检查
- 使用 API 网关进行访问控制
- 敏感操作添加二次确认
- 定期审计对话日志
7. 常见问题排查
7.1 性能问题
症状:响应时间超过 5 秒
- 检查网络延迟:
traceroute api.dashscope.aliyun.com - 降低
max-tokens参数 - 启用流式响应改善用户体验
7.2 记忆失效
症状:对话丢失上下文
- 确认
conversationId是否保持一致 - 检查 Redis 内存使用情况
- 验证
MessageWindowChatMemory配置
7.3 工具调用失败
症状:AI 无法正确使用工具
- 检查工具描述是否清晰
- 验证输入参数是否符合 JSON Schema
- 在测试环境模拟工具调用
8. 项目配置参考
8.1 Maven 依赖
xml复制<dependencies>
<!-- 核心依赖 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-agent-framework</artifactId>
<version>1.1.2.0</version>
</dependency>
<!-- DashScope 适配器 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
<version>1.1.2.0</version>
</dependency>
<!-- 可选组件 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-graph</artifactId>
<version>1.1.2.0</version>
</dependency>
</dependencies>
8.2 应用配置
properties复制# 生产环境推荐配置
spring.ai.dashscope.api-key=${AI_API_KEY}
spring.ai.dashscope.chat.options.model=qwen-max
spring.ai.dashscope.chat.options.temperature=0.7
# 记忆存储配置
spring.ai.memory.redis.host=redis.prod.svc.cluster.local
spring.ai.memory.redis.timeout=3000
9. 扩展阅读
-
性能优化:对于高并发场景,建议:
- 实现本地缓存减少重复计算
- 使用异步非阻塞调用
- 考虑模型量化降低推理成本
-
领域适配:要获得更好的领域表现:
- 微调基础模型
- 构建领域特定的工具集
- 设计针对性的提示词模板
-
架构演进:复杂系统可以考虑:
- 引入智能体编排引擎
- 实现动态工具加载
- 构建评估反馈闭环
在实际项目中,我们团队发现最有效的优化方式是从小规模试点开始,逐步收集用户反馈,再针对性扩展功能。Spring AI Alibaba 的模块化设计特别适合这种渐进式演进策略。
