Spring AI 实战:从零构建企业级 AI 智能体应用(含 RAG、Function Calling、多模态)
项目地址:https://gitee.com/vivowushi/springai
目录
[1.1 项目简介](#1.1 项目简介)
[1.2 学习路线图](#1.2 学习路线图)
[2.1 技术栈](#2.1 技术栈)
[2.2 系统架构](#2.2 系统架构)
[3.1 项目结构](#3.1 项目结构)
[3.2 Maven 依赖配置](#3.2 Maven 依赖配置)
[4.1 AI 配置类](#4.1 AI 配置类)
[4.2 统一控制器设计](#4.2 统一控制器设计)
[4.3 会话管理服务](#4.3 会话管理服务)
[五、RAG 知识库实战](#五、RAG 知识库实战)
[5.1 RAG 工作原理](#5.1 RAG 工作原理)
[5.2 RAG 控制器实现](#5.2 RAG 控制器实现)
[5.3 知识库服务实现](#5.3 知识库服务实现)
[六、Function Calling 工具调用](#六、Function Calling 工具调用)
[6.1 工具服务实现](#6.1 工具服务实现)
[6.2 Function Calling 调用示例](#6.2 Function Calling 调用示例)
[7.1 文生图服务](#7.1 文生图服务)
[7.2 语音合成服务](#7.2 语音合成服务)
[8.1 环境要求](#8.1 环境要求)
[8.2 配置文件](#8.2 配置文件)
[8.3 启动项目](#8.3 启动项目)
[8.4 接口测试](#8.4 接口测试)
[9.1 项目亮点](#9.1 项目亮点)
[9.2 技术难点与解决方案](#9.2 技术难点与解决方案)
[9.3 未来规划](#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 核心 API | AssistantController.java |
| 第3周 | 结构化输出、Prompt 模板、会话记忆 | ConversationService.java |
| 第4周 | Function Calling、天气查询、计算器 | ToolService.java |
| 第5周 | RAG 与 Milvus 入门、向量数据库 | RagController.java |
| 第6周 | 企业级 RAG 知识库、AI 网站助手 | 全项目整合 |
二、技术架构与选型
2.1 技术栈
| 类别 | 技术 | 版本 | 说明 |
|---|---|---|---|
| 基础框架 | Spring Boot | 3.2.10 | 企业级应用框架 |
| AI 框架 | Spring AI | 1.0.0 | Spring 官方 AI 开发框架 |
| 云服务 | Spring AI Alibaba | 1.0.0.4 | 阿里云 DashScope 集成 |
| 本地模型 | Ollama | - | 本地部署 DeepSeek/Qwen |
| 向量数据库 | Milvus | 2.4.4 | 高性能向量检索 |
| 编程语言 | Java | 21 | 使用最新 LTS 版本 |
| 构建工具 | Maven | 3.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 依赖配置
java
<!-- 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 配置类
java
@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 统一控制器设计
java
@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 会话管理服务
java
@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 控制器实现
java
@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 知识库服务实现
java
@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 工具服务实现
java
@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 调用示例
java
// 使用 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 文生图服务
java
@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 语音合成服务
java
@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 配置文件
java
# 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 启动项目
java
# 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 接口测试
java
# 基础聊天
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 项目亮点
- 多模型支持:DashScope 云端 + Ollama 本地,灵活切换
- 完整 AI 能力:对话、文生图、语音、工具调用、RAG
- 流式响应:SSE 实现实时输出,提升用户体验
- 教学友好:模块化设计,对应教学实验内容
- 企业级架构:分层设计、依赖注入、配置外置
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/
💬 交流与反馈
如果你对这个项目有任何问题或建议,欢迎在评论区留言交流!
如果觉得这篇文章对你有帮助,别忘了点赞 👍 和收藏 ⭐ 哦~