SpringAI构建智能体
2026/6/10 9:31:00 网站建设 项目流程

Spring AI 实战:从零构建企业级 AI 智能体应用(含 RAG、Function Calling、多模态)

项目地址:https://gitee.com/vivowushi/springai

目录

一、项目背景与目标

1.1 项目简介

1.2 学习路线图

二、技术架构与选型

2.1 技术栈

2.2 系统架构

三、核心功能模块详解

3.1 项目结构

3.2 Maven 依赖配置

四、代码实现与最佳实践

4.1 AI 配置类

4.2 统一控制器设计

4.3 会话管理服务

五、RAG 知识库实战

5.1 RAG 工作原理

5.2 RAG 控制器实现

5.3 知识库服务实现

六、Function Calling 工具调用

6.1 工具服务实现

6.2 Function Calling 调用示例

七、多模态能力实现

7.1 文生图服务

7.2 语音合成服务

八、项目运行与测试

8.1 环境要求

8.2 配置文件

8.3 启动项目

8.4 接口测试

九、总结与展望

9.1 项目亮点

9.2 技术难点与解决方案

9.3 未来规划

📚 学习资源

💬 交流与反馈


一、项目背景与目标

1.1 项目简介

本项目是《计算机科学与技术专业》实践课程的教学案例项目,基于Spring AI Alibaba+DashScope+Ollama构建完整的 AI 智能体应用。

项目涵盖了当前 AI 应用开发的核心技术栈:

  • 🔤大模型调用:DashScope 云端 API + Ollama 本地模型
  • 💬多轮对话:会话管理、上下文记忆
  • 🛠️Function Calling:工具调用、智能决策
  • 📚RAG 知识库:Milvus 向量数据库、文档检索
  • 🎨多模态:文生图、语音合成
  • 流式响应:SSE 实时输出

1.2 学习路线图

周次学习内容对应模块
第1周Ollama 本地部署、Spring AI Alibaba 入门AiConfig.java
第2周DeepSeek 聊天接口、Spring AI 核心 APIAssistantController.java
第3周结构化输出、Prompt 模板、会话记忆ConversationService.java
第4周Function Calling、天气查询、计算器ToolService.java
第5周RAG 与 Milvus 入门、向量数据库RagController.java
第6周企业级 RAG 知识库、AI 网站助手全项目整合

二、技术架构与选型

2.1 技术栈

类别技术版本说明
基础框架Spring Boot3.2.10企业级应用框架
AI 框架Spring AI1.0.0Spring 官方 AI 开发框架
云服务Spring AI Alibaba1.0.0.4阿里云 DashScope 集成
本地模型Ollama-本地部署 DeepSeek/Qwen
向量数据库Milvus2.4.4高性能向量检索
编程语言Java21使用最新 LTS 版本
构建工具Maven3.8+依赖管理

2.2 系统架构

┌─────────────────────────────────────────────────────────────┐ │ 客户端层 │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Web 前端 │ │ 移动端 App │ │ 第三方系统 │ │ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ └─────────┼─────────────────┼─────────────────┼───────────────┘ │ │ │ └─────────────────┼─────────────────┘ │ HTTP/SSE ┌───────────────────────────┼───────────────────────────────────┐ │ Spring Boot 后端 │ │ │ │ │ ┌───────────────────────┴───────────────────────────────┐ │ │ │ 控制器层 │ │ │ │ ┌────────────┐ ┌────────────┐ ┌──────────────────┐ │ │ │ │ │ Assistant │ │ RAG │ │ 其他... │ │ │ │ │ │ Controller │ │ Controller │ │ │ │ │ │ │ └─────┬──────┘ └─────┬──────┘ └──────────────────┘ │ │ │ └────────┼─────────────┼───────────────────────────────┘ │ │ │ │ │ │ ┌────────┴─────────────┴───────────────────────────────┐ │ │ │ 服务层 │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ │ │ │ │ 对话服务 │ │ 图片服务 │ │ 语音服务 │ │工具服务 │ │ │ │ │ └──────────┘ └──────────┘ └──────────┘ └─────────┘ │ │ │ └───────────────────────┬───────────────────────────────┘ │ │ │ │ │ ┌───────────────────────┴───────────────────────────────┐ │ │ │ 数据访问层 │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │ │ │ │ │ Conversation │ │ Message │ │ Document │ │ │ │ │ │ Repository │ │ Repository │ │ Repository │ │ │ │ │ └──────────────┘ └──────────────┘ └─────────────┘ │ │ │ └───────────────────────────────────────────────────────┘ │ │ │ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌──────────┐ │ │ │ DashScope │ │ Ollama │ │ Milvus │ │ 文件存储 │ │ │ │ (云端API) │ │ (本地) │ │ (向量库) │ │ │ │ │ └────────────┘ └────────────┘ └────────────┘ └──────────┘ │ └──────────────────────────────────────────────────────────────┘

三、核心功能模块详解

3.1 项目结构

ai-demo/ ├── src/main/java/org/example/aidemo/ │ ├── AiDemoApplication.java # 启动类 │ ├── config/ │ │ └── AiConfig.java # AI 配置(ChatClient、语音) │ ├── assistant/ │ │ └── AssistantController.java # AI 助手主控制器 │ ├── rag/ │ │ └── RagController.java # RAG 知识库控制器 │ ├── model/ # 数据模型 │ │ ├── ChatMessage.java │ │ ├── Conversation.java │ │ ├── CalculatorRequest.java │ │ ├── ImageRequest.java │ │ ├── KnowledgeDocument.java │ │ ├── SearchResult.java │ │ ├── SpeechRequest.java │ │ └── WeatherInfo.java │ └── service/ # 业务服务层 │ ├── ConversationService.java # 会话管理 │ ├── ImageService.java # 文生图 │ ├── SpeechService.java # 语音合成 │ ├── ToolService.java # 工具调用 │ ├── WebsiteAssistantService.java # 网站助手 │ └── KnowledgeBaseService.java # 知识库管理 └── src/main/resources/ └── application.yml # 配置文件

3.2 Maven 依赖配置

<!-- pom.xml 核心依赖 --> <dependencies> <!-- Spring Boot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring AI Ollama 本地模型 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-ollama</artifactId> <version>1.0.0</version> </dependency> <!-- Spring AI Alibaba DashScope --> <dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-starter-dashscope</artifactId> <version>1.0.0.4</version> </dependency> <!-- Milvus 向量数据库 --> <dependency> <groupId>io.milvus</groupId> <artifactId>milvus-sdk-java</artifactId> <version>2.4.4</version> </dependency> <!-- Spring AI Milvus 集成 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-vector-store-milvus</artifactId> <version>1.0.0</version> </dependency> <!-- Lombok 简化开发 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>

四、代码实现与最佳实践

4.1 AI 配置类

@Configuration public class AiConfig { /** * DashScope 聊天客户端(云端 API) * 支持 qwen-turbo、qwen-plus、qwen-max 等模型 */ @Bean public ChatClient dashscopeChatClient(DashScopeChatModel dashScopeChatModel) { return ChatClient.builder(dashScopeChatModel).build(); } /** * Ollama 聊天客户端(本地模型) * 支持 DeepSeek、Qwen2.5 等本地部署模型 */ @Bean public ChatClient ollamaChatClient(OllamaChatModel ollamaChatModel) { return ChatClient.builder(ollamaChatModel).build(); } /** * 默认聊天客户端(优先使用 DashScope) */ @Bean @Primary public ChatClient defaultChatClient(DashScopeChatModel dashScopeChatModel) { return ChatClient.builder(dashScopeChatModel).build(); } /** * 语音合成服务 * 直接暴露自动配置的 DashScopeAudioSpeechModel */ @Bean("dashScopeSpeechClient") public SpeechSynthesisModel dashScopeSpeechClient(DashScopeAudioSpeechModel speechModel) { return speechModel; } }

4.2 统一控制器设计

@RestController @RequestMapping("/api/assistant") public class AssistantController { private final WebsiteAssistantService websiteAssistantService; private final ConversationService conversationService; private final ImageService imageService; private final SpeechService speechService; private final ToolService toolService; private final ChatClient dashscopeChatClient; private final ChatClient ollamaChatClient; // 构造器注入(推荐方式) public AssistantController( WebsiteAssistantService websiteAssistantService, ConversationService conversationService, ImageService imageService, SpeechService speechService, ToolService toolService, ChatClient dashscopeChatClient, ChatClient ollamaChatClient) { this.websiteAssistantService = websiteAssistantService; // ... 其他注入 } // ==================== 基础聊天 ==================== /** * 基础聊天(默认模型) */ @PostMapping("/chat") public ResponseEntity<Map<String, String>> chat(@RequestBody Map<String, String> request) { String message = request.get("message"); String response = websiteAssistantService.chat(message); return ResponseEntity.ok(Map.of("response", response)); } /** * DashScope 模型聊天 */ @PostMapping("/dashscope/chat") public ResponseEntity<Map<String, String>> dashscopeChat(@RequestBody Map<String, String> request) { String message = request.get("message"); String systemPrompt = request.getOrDefault("systemPrompt", "你是一个有用的AI助手。"); String response = dashscopeChatClient.prompt() .system(systemPrompt) .user(message) .call() .content(); return ResponseEntity.ok(Map.of("response", response)); } /** * Ollama 本地模型流式聊天(SSE) * 使用 Flux 实现服务端推送 */ @PostMapping("/ollama/stream") public Flux<String> ollamaChatStream(@RequestBody Map<String, String> request) { String message = request.get("message"); return ollamaChatClient.prompt() .user(message) .stream() .content(); } }

4.3 会话管理服务

@Service public class ConversationService { // 内存存储会话(生产环境建议使用数据库) private final Map<String, Conversation> conversations = new ConcurrentHashMap<>(); /** * 创建新会话 */ public Conversation createConversation(String model) { String id = UUID.randomUUID().toString(); Conversation conv = new Conversation(); conv.setId(id); conv.setModel(model); conv.setMessages(new ArrayList<>()); conv.setCreatedAt(LocalDateTime.now()); conversations.put(id, conv); return conv; } /** * 多轮对话(带历史上下文) */ public String multiRoundChat(String conversationId, String userMessage) { Conversation conv = conversations.get(conversationId); if (conv == null) { throw new RuntimeException("会话不存在"); } // 添加用户消息 ChatMessage userMsg = new ChatMessage("user", userMessage); conv.getMessages().add(userMsg); // 构建历史上下文 StringBuilder historyPrompt = new StringBuilder(); for (ChatMessage msg : conv.getMessages()) { if ("user".equals(msg.getRole())) { historyPrompt.append("用户: ").append(msg.getContent()).append("\n"); } else { historyPrompt.append("助手: ").append(msg.getContent()).append("\n"); } } // 调用 AI 获取回复 String response = websiteAssistantService.chat(historyPrompt.toString()); // 保存助手回复 ChatMessage assistantMsg = new ChatMessage("assistant", response); conv.getMessages().add(assistantMsg); return response; } }

五、RAG 知识库实战

5.1 RAG 工作原理

┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 文档上传 │────▶│ 文本切分 │────▶│ 向量化 │ │ (PDF/Word) │ │ (Chunking) │ │ (Embedding) │ └─────────────┘ └─────────────┘ └──────┬──────┘ │ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 用户提问 │────▶│ 向量检索 │────▶│ Milvus │ │ │ │ (Similarity)│ │ 向量数据库 │ └─────────────┘ └─────────────┘ └──────┬───────┘ │ ▼ ┌─────────────┐ │ 上下文组装 │ │ (Prompt) │ └──────┬──────┘ │ ▼ ┌─────────────┐ │ LLM 生成 │ │ (Answer) │ └─────────────┘

5.2 RAG 控制器实现

@RestController @RequestMapping("/api/rag") public class RagController { private final KnowledgeBaseService knowledgeBaseService; /** * 上传文本文档 */ @PostMapping("/document") public ResponseEntity<Map<String, String>> uploadDocument(@RequestBody KnowledgeDocument doc) { knowledgeBaseService.addDocument(doc.getTitle(), doc.getContent()); return ResponseEntity.ok(Map.of( "message", "文档上传成功", "title", doc.getTitle() )); } /** * 上传文件 */ @PostMapping("/document/upload") public ResponseEntity<Map<String, String>> uploadFile(@RequestParam("file") MultipartFile file) { try { String content = new String(file.getBytes(), StandardCharsets.UTF_8); knowledgeBaseService.addDocument(file.getOriginalFilename(), content); return ResponseEntity.ok(Map.of( "message", "文件上传成功", "filename", file.getOriginalFilename() )); } catch (IOException e) { return ResponseEntity.badRequest().body(Map.of("error", e.getMessage())); } } /** * 知识搜索 */ @GetMapping("/search") public ResponseEntity<List<SearchResult>> search(@RequestParam String query) { List<SearchResult> results = knowledgeBaseService.search(query); return ResponseEntity.ok(results); } /** * 智能问答(RAG) */ @PostMapping("/ask") public ResponseEntity<Map<String, Object>> ask(@RequestBody Map<String, String> request) { String question = request.get("question"); Map<String, Object> answer = knowledgeBaseService.ask(question); return ResponseEntity.ok(answer); } /** * 知识库统计 */ @GetMapping("/stats") public ResponseEntity<Map<String, Object>> getStats() { Map<String, Object> stats = knowledgeBaseService.getStats(); return ResponseEntity.ok(stats); } }

5.3 知识库服务实现

@Service public class KnowledgeBaseService { private final VectorStore vectorStore; private final ChatClient defaultClient; /** * 添加文档到知识库 */ public void addDocument(String title, String content) { // 文本切分(简单实现:按段落分割) String[] chunks = content.split("\n\n"); for (String chunk : chunks) { if (chunk.trim().isEmpty()) continue; // 创建文档嵌入 Document document = new Document(Map.of( "title", title, "content", chunk.trim() )); vectorStore.add(List.of(document)); } } /** * 知识搜索 */ public List<SearchResult> search(String query) { List<Document> documents = vectorStore.similaritySearch(query); return documents.stream() .map(doc -> new SearchResult( doc.getId(), doc.getContent(), doc.getScore(), "knowledge_base" )) .toList(); } /** * RAG 智能问答 */ public Map<String, Object> ask(String question) { // 1. 检索相关文档 List<Document> relevantDocs = vectorStore.similaritySearch(question); // 2. 构建上下文 StringBuilder context = new StringBuilder(); for (Document doc : relevantDocs) { context.append(doc.getContent()).append("\n\n"); } // 3. 构建 Prompt String prompt = String.format(""" 基于以下知识库内容回答用户问题: 知识库内容: %s 用户问题:%s 请根据知识库内容准确回答,如果知识库中没有相关信息,请如实告知。 """, context.toString(), question); // 4. 调用 LLM 生成回答 String answer = defaultClient.prompt() .user(prompt) .call() .content(); // 5. 返回结果 List<String> sources = relevantDocs.stream() .map(Document::getContent) .toList(); return Map.of( "answer", answer, "sources", sources, "success", true ); } }

六、Function Calling 工具调用

6.1 工具服务实现

@Service public class ToolService { private final ChatClient defaultClient; /** * 天气查询工具 */ public String queryWeather(String city) { // 模拟天气数据(实际项目可接入和风天气、OpenWeather 等 API) return String.format( "【天气查询结果】\n" + "城市: %s\n" + "天气: 多云转晴\n" + "温度: 23°C\n" + "湿度: 65%%\n" + "风力: 东北风3级", city ); } /** * 计算器工具 - 安全表达式计算 */ public String calculate(String expression) { try { // 安全校验:只允许数字和运算符 if (!expression.matches("[0-9+\\-*/().\\s]+")) { return "错误:表达式包含非法字符"; } double result = evaluateExpression(expression); return String.format("计算结果: %s = %.4f", expression, result); } catch (Exception e) { return "计算错误: " + e.getMessage(); } } /** * 智能工具调用 - AI 自动判断调用哪个工具 */ public String smartToolCall(String userInput) { String systemPrompt = """ 你是一个智能助手,可以根据用户输入判断需要调用哪个工具。 可用工具: 1. 天气查询 - 当用户询问天气时,返回格式:WEATHER:城市名 2. 计算器 - 当用户需要进行数学计算时,返回格式:CALCULATE:数学表达式 如果不需要调用工具,直接回答用户问题。 只返回工具调用格式或直接回答,不要有其他内容。 """; String response = defaultClient.prompt() .system(systemPrompt) .user(userInput) .call() .content(); // 解析工具调用 if (response.startsWith("WEATHER:")) { String city = response.substring(8).trim(); return queryWeather(city); } else if (response.startsWith("CALCULATE:")) { String expr = response.substring(10).trim(); return calculate(expr); } return response; } /** * 简单表达式计算器实现 */ private double evaluateExpression(String expr) { expr = expr.replaceAll("\\s+", ""); // 处理加减法 String[] parts = expr.split("(?=[-+])|(?<=[-+])"); double result = 0; boolean isAddition = true; for (String part : parts) { if (part.isEmpty()) continue; if (part.equals("+")) { isAddition = true; continue; } if (part.equals("-")) { isAddition = false; continue; } // 处理乘除 double value = evaluateMulDiv(part); result = isAddition ? result + value : result - value; } return result; } private double evaluateMulDiv(String expr) { String[] parts = expr.split("(?=[*/])|(?<=[*/])"); double result = Double.parseDouble(parts[0]); for (int i = 1; i < parts.length; i += 2) { String op = parts[i]; double val = Double.parseDouble(parts[i + 1]); result = op.equals("*") ? result * val : result / val; } return result; } }

6.2 Function Calling 调用示例

// 使用 Spring AI 的 Function Calling 特性 @Bean public ToolCallingChatClient toolCallingChatClient(ChatClient.Builder builder) { return builder .defaultTools(new WeatherFunction(), new CalculatorFunction()) .build(); } // 定义天气工具函数 public class WeatherFunction implements Function<WeatherRequest, String> { @Override public String apply(WeatherRequest request) { return queryWeather(request.getCity()); } } // 定义计算器工具函数 public class CalculatorFunction implements Function<CalculatorRequest, String> { @Override public String apply(CalculatorRequest request) { return calculate(request.getExpression()); } }

七、多模态能力实现

7.1 文生图服务

@Service public class ImageService { private final ChatClient dashscopeChatClient; /** * 文生图 */ public String generateImage(String prompt) { // 调用 DashScope 文生图 API ImageResponse response = dashscopeChatClient.prompt() .user("生成图片:" + prompt) .call() .entity(ImageResponse.class); return response.getImageUrl(); } /** * 文生图(优化提示词) * 先让 AI 优化提示词,再生成图片 */ public String generateImageWithOptimization(String prompt) { // 1. AI 优化提示词 String enhancedPrompt = dashscopeChatClient.prompt() .system("你是一个专业的 AI 绘画提示词工程师,请优化用户的绘画描述,使其更详细、更具艺术感。") .user(prompt) .call() .content(); // 2. 使用优化后的提示词生成图片 return generateImage(enhancedPrompt); } }

7.2 语音合成服务

@Service public class SpeechService { @Qualifier("dashScopeSpeechClient") private final SpeechSynthesisModel speechModel; /** * 文本转语音 */ public byte[] textToSpeech(String text, String voice, Double speed) { SpeechSynthesisRequest request = SpeechSynthesisRequest.builder() .text(text) .voice(voice != null ? voice : "alloy") .speed(speed != null ? speed : 1.0) .build(); SpeechSynthesisResponse response = speechModel.call(request); return response.getAudioData(); } }

八、项目运行与测试

8.1 环境要求

  • JDK 21
  • Maven 3.8+
  • DashScope API Key(阿里云灵积)
  • Ollama(可选,用于本地模型)

8.2 配置文件

# src/main/resources/application.yml spring: application: name: ai-demo ai: # Ollama 本地模型配置 ollama: base-url: http://localhost:11434 chat: options: model: qwen2.5:3b temperature: 0.7 # DashScope 云端 API 配置 dashscope: api-key: sk-xxxxxxxxxxxxxxxx # 替换为你的 API Key chat: options: model: qwen-plus # 可选: qwen-turbo, qwen-plus, qwen-max temperature: 0.7 # Milvus 向量数据库配置 vectorstore: milvus: client: host: localhost port: 19530 database-name: ai_demo collection-name: knowledge_base embedding-dimension: 768 server: port: 8080

8.3 启动项目

# 1. 克隆项目 git clone <repository-url> cd ai-demo # 2. 配置 API Key # 编辑 src/main/resources/application.yml,填入 DashScope API Key # 3. 启动项目 ./mvnw spring-boot:run # 或使用 IDEA 直接运行 AiDemoApplication.java

8.4 接口测试

# 基础聊天 curl -X POST http://localhost:8080/api/assistant/chat \ -H "Content-Type: application/json" \ -d '{"message": "你好,请介绍一下 Spring AI"}' # 文生图 curl -X POST http://localhost:8080/api/assistant/image/generate \ -H "Content-Type: application/json" \ -d '{"prompt": "一只可爱的猫咪在草地上玩耍"}' # 天气查询 curl "http://localhost:8080/api/assistant/tools/weather?city=南京" # 计算器 curl "http://localhost:8080/api/assistant/tools/calculate?expression=12*(3+4)" # RAG 问答 curl -X POST http://localhost:8080/api/rag/ask \ -H "Content-Type: application/json" \ -d '{"question": "Spring AI 是什么?"}'

九、总结与展望

9.1 项目亮点

  1. 多模型支持:DashScope 云端 + Ollama 本地,灵活切换
  2. 完整 AI 能力:对话、文生图、语音、工具调用、RAG
  3. 流式响应:SSE 实现实时输出,提升用户体验
  4. 教学友好:模块化设计,对应教学实验内容
  5. 企业级架构:分层设计、依赖注入、配置外置

9.2 技术难点与解决方案

难点解决方案
多模型切换使用@Primary@Qualifier注解管理不同 ChatClient
流式响应使用 Spring WebFlux 的Flux<String>返回 SSE
向量数据库集成Spring AI 提供的VectorStore抽象层
工具调用解析AI 返回结构化格式,后端解析执行
会话历史管理内存 Map 存储(生产环境替换为数据库)

9.3 未来规划

  • [ ] 接入真实天气 API(和风天气、OpenWeather)
  • [ ] MySQL 持久化会话和知识库数据
  • [ ] 前端页面开发(Vue/React + SSE 流式渲染)
  • [ ] 用户认证与权限控制(Spring Security)
  • [ ] 更多工具扩展(搜索、翻译、代码执行)
  • [ ] 微服务架构改造
  • [ ] 监控与日志(Micrometer + Grafana)

📚 学习资源

  • Spring AI 官方文档:Introduction :: Spring AI Reference
  • Spring AI Alibaba:https://github.com/alibaba/spring-ai-alibaba
  • DashScope 开放平台:大模型服务平台百炼 - 大模型应用构建 - 阿里云
  • Milvus 文档:https://milvus.io/docs
  • Ollama 官网:https://ollama.com/

💬 交流与反馈

如果你对这个项目有任何问题或建议,欢迎在评论区留言交流!

如果觉得这篇文章对你有帮助,别忘了点赞 👍 和收藏 ⭐ 哦~

项目地址:https://gitee.com/vivowushi/springai

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询