492 lines
11 KiB
Markdown
492 lines
11 KiB
Markdown
# Spring AI 企业级应用开发培训
|
|
|
|
## 📋 大纲
|
|
|
|
1. [AI 开发基础概念](#1-ai-开发基础概念)
|
|
2. [Spring AI 框架介绍](#2-spring-ai-框架介绍)
|
|
3. [实战演练](#3-实战演练)
|
|
|
|
|
|
**前置知识**: Spring Boot 基础、RESTful API
|
|
|
|
---
|
|
|
|
## 1. AI 开发基础概念
|
|
|
|
### 1.1 大语言模型(LLM)是什么?
|
|
|
|
```
|
|
传统编程: 输入 + 规则 = 输出
|
|
AI 编程: 输入 + 示例 + 指令 = 输出
|
|
```
|
|
|
|
**核心能力**:
|
|
|
|
- 自然语言理解
|
|
- 文本生成
|
|
- 逻辑推理
|
|
- 代码生成
|
|
|
|
### 1.2 Prompt Engineering(提示工程)
|
|
|
|
**Prompt 的组成**:
|
|
```
|
|
系统提示(System): 定义角色和行为规则
|
|
用户消息(User): 具体问题或任务
|
|
上下文(Context): 历史对话或相关知识
|
|
```
|
|
|
|
**最佳实践**:
|
|
```java
|
|
// ❌ 差的 Prompt
|
|
"帮我写个排序算法"
|
|
|
|
// ✅ 好的 Prompt
|
|
"""
|
|
你是一位资深Java工程师。请实现一个快速排序算法,要求:
|
|
1. 使用泛型支持任意Comparable类型
|
|
2. 添加详细注释
|
|
3. 包含单元测试示例
|
|
4. 分析时间复杂度
|
|
"""
|
|
```
|
|
|
|
### 1.3 RAG (检索增强生成)
|
|
|
|
**为什么需要 RAG?**
|
|
|
|
- LLM 的知识有截止时间
|
|
- 企业内部数据不在训练集中
|
|
- 减少幻觉(Hallucination)
|
|
|
|
**工作原理**:
|
|
```
|
|
用户问题 → 向量化 → 检索相关文档 → 拼接Prompt → LLM生成答案
|
|
```
|
|
|
|
### 1.4 Function Calling (工具调用)
|
|
|
|
让 AI 能够调用外部工具:
|
|
- 查询数据库
|
|
- 调用 API
|
|
- 执行计算
|
|
|
|
---
|
|
|
|
## 2. Spring AI 框架介绍
|
|
|
|
### 2.1 为什么选择 Spring AI?
|
|
|
|
**优势**:
|
|
- ✅ 与 Spring 生态无缝集成
|
|
- ✅ 统一的模型抽象(支持多厂商)
|
|
- ✅ 企业级特性(安全、限流、重试)
|
|
- ✅ 熟悉的编程模型
|
|
|
|
**对比其他框架**:
|
|
| 特性 | Spring AI | LangChain4j | LlamaIndex |
|
|
|------|-----------|-------------|------------|
|
|
| Spring 集成 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
|
|
| 学习曲线 | 平缓 | 中等 | 陡峭 |
|
|
|
|
### 2.2 架构设计
|
|
|
|
```
|
|
┌──────────────────────────────────────┐
|
|
│ 业务代码 (Your Service) │
|
|
├──────────────────────────────────────┤
|
|
│ AgentTemplate / RagTemplate │ ← 我们封装的模板
|
|
├──────────────────────────────────────┤
|
|
│ ChatClient (Spring AI) │ ← 统一客户端
|
|
├──────────────────────────────────────┤
|
|
│ OpenAI / Ollama / DashScope │ ← 具体模型
|
|
└──────────────────────────────────────┘
|
|
```
|
|
|
|
### 2.3 核心模块概览
|
|
|
|
#### Agent Starter - 对话能力
|
|
```java
|
|
// 一行代码实现对话
|
|
String answer = agentTemplate.ask("什么是Spring AI?");
|
|
```
|
|
|
|
#### RAG Starter - 知识库问答
|
|
```java
|
|
// 基于企业知识库回答
|
|
String answer = ragTemplate.ask("公司的报销流程是什么?");
|
|
```
|
|
|
|
#### MCP Starter - 工具调用
|
|
```java
|
|
@Tool(description = "查询天气")
|
|
public String getWeather(String city) {
|
|
return weatherService.query(city);
|
|
}
|
|
```
|
|
|
|
#### Graph Starter - 工作流编排
|
|
```java
|
|
// 顺序执行多个步骤
|
|
var result = GraphTemplate.sequential(
|
|
node1, node2, node3
|
|
).execute(input);
|
|
```
|
|
|
|
---
|
|
|
|
## 3. 实战演练
|
|
|
|
### 3.1 场景一: 智能客服机器人
|
|
|
|
**需求**:
|
|
- 回答常见问题
|
|
- 支持多轮对话
|
|
- 能查询订单状态
|
|
|
|
**实现**:
|
|
|
|
```java
|
|
@Service
|
|
public class CustomerBotService {
|
|
|
|
@Autowired
|
|
private AgentTemplate agentTemplate;
|
|
|
|
@Autowired
|
|
private OrderService orderService;
|
|
|
|
/**
|
|
* 处理用户咨询
|
|
*/
|
|
public String chat(String sessionId, String message) {
|
|
// 1. 尝试从知识库回答
|
|
String knowledgeAnswer = ragTemplate.ask(message);
|
|
|
|
// 2. 如果知识库没有,使用通用对话
|
|
if (isNotConfident(knowledgeAnswer)) {
|
|
return agentTemplate.askWithMemory(sessionId, message);
|
|
}
|
|
|
|
return knowledgeAnswer;
|
|
}
|
|
|
|
/**
|
|
* 查询订单(工具调用示例)
|
|
*/
|
|
@Tool(description = "查询订单状态")
|
|
public String queryOrder(@ToolParam(description = "订单号") String orderId) {
|
|
Order order = orderService.findById(orderId);
|
|
return "订单状态: " + order.getStatus();
|
|
}
|
|
}
|
|
```
|
|
|
|
**配置**:
|
|
```yaml
|
|
spring:
|
|
ai:
|
|
openai:
|
|
chat:
|
|
options:
|
|
model: gpt-4
|
|
temperature: 0.7 # 创造性: 0-1,越高越有创意
|
|
|
|
app:
|
|
ai:
|
|
safety:
|
|
block-keywords:
|
|
- 密码
|
|
- 身份证号
|
|
```
|
|
|
|
---
|
|
|
|
### 3.2 场景二: 智能文档助手
|
|
|
|
**需求**:
|
|
- 上传 PDF/Word 文档
|
|
- 基于文档内容问答
|
|
- 提取关键信息
|
|
|
|
**实现**:
|
|
|
|
```java
|
|
@Service
|
|
public class DocumentAssistantService {
|
|
|
|
@Autowired
|
|
private VectorStore vectorStore;
|
|
|
|
@Autowired
|
|
private RagTemplate ragTemplate;
|
|
|
|
/**
|
|
* 导入文档到知识库
|
|
*/
|
|
public void importDocument(MultipartFile file) {
|
|
// 1. 解析文档
|
|
List<Document> documents = documentParser.parse(file);
|
|
|
|
// 2. 切片(Chunking)
|
|
List<Document> chunks = documentSplitter.split(documents);
|
|
|
|
// 3. 向量化并存储
|
|
vectorStore.add(chunks);
|
|
}
|
|
|
|
/**
|
|
* 基于文档问答
|
|
*/
|
|
public String askAboutDocument(String question, String docCategory) {
|
|
// 添加过滤条件,只搜索特定类别的文档
|
|
return ragTemplate.askWithConfig(
|
|
question,
|
|
0.75, // 相似度阈值
|
|
3 // TopK
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 提取文档摘要
|
|
*/
|
|
public String extractSummary(String documentId) {
|
|
String content = documentRepository.findById(documentId);
|
|
|
|
return agentTemplate.askForObject(
|
|
"请总结以下文档的核心要点,以列表形式返回:\n" + content,
|
|
DocumentSummary.class
|
|
);
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3.3 场景三: 代码审查助手
|
|
|
|
**需求**:
|
|
- 自动审查提交的代码
|
|
- 发现潜在问题
|
|
- 给出改进建议
|
|
|
|
**实现**:
|
|
|
|
```java
|
|
@Service
|
|
public class CodeReviewService {
|
|
|
|
@Autowired
|
|
private AgentTemplate agentTemplate;
|
|
|
|
/**
|
|
* 审查代码
|
|
*/
|
|
public CodeReviewResult review(String code, String language) {
|
|
String prompt = """
|
|
你是一位资深的%s工程师,请审查以下代码:
|
|
|
|
检查项:
|
|
1. 代码规范
|
|
2. 潜在bug
|
|
3. 性能问题
|
|
4. 安全漏洞
|
|
5. 可维护性
|
|
|
|
代码:
|
|
```%s
|
|
%s
|
|
```
|
|
|
|
请以JSON格式返回审查结果。
|
|
""".formatted(language, language, code);
|
|
|
|
return agentTemplate.askForObject(prompt, CodeReviewResult.class);
|
|
}
|
|
|
|
/**
|
|
* 批量审查(并行处理)
|
|
*/
|
|
public List<CodeReviewResult> batchReview(List<CodeFile> files) {
|
|
var nodes = files.stream()
|
|
.map(file -> GraphTemplate.node(
|
|
"审查_" + file.getName(),
|
|
f -> review(f.getContent(), f.getLanguage())
|
|
))
|
|
.toArray(Node[]::new);
|
|
|
|
var workflow = GraphTemplate.parallel(nodes);
|
|
return workflow.execute(files);
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 4. 高级主题
|
|
|
|
### 4.1 工作流编排模式
|
|
|
|
#### 模式一: 链式处理 (Sequential)
|
|
```
|
|
输入 → 节点1 → 节点2 → 节点3 → 输出
|
|
```
|
|
|
|
**适用场景**: 数据清洗流水线、ETL 流程
|
|
|
|
#### 模式二: 分支路由 (Routing)
|
|
```
|
|
┌→ 节点A →┐
|
|
输入 → 路由 → 合并 → 输出
|
|
└→ 节点B →┘
|
|
```
|
|
|
|
**适用场景**: 根据问题类型选择不同处理逻辑
|
|
|
|
#### 模式三: 并行聚合 (Parallel)
|
|
```
|
|
输入 → 节点1 ─┐
|
|
输入 → 节点2 ─┼→ 聚合 → 输出
|
|
输入 → 节点3 ─┘
|
|
```
|
|
|
|
**适用场景**: 多维度分析、批量处理
|
|
|
|
#### 模式四: 循环优化 (Loop)
|
|
```
|
|
输入 → 节点 → 评估 → 不满足 → 回到节点
|
|
↓
|
|
满足 → 输出
|
|
```
|
|
|
|
**适用场景**: 迭代优化、自我修正
|
|
|
|
---
|
|
|
|
### 4.2 性能优化技巧
|
|
|
|
#### 技巧一: 缓存策略
|
|
```java
|
|
@Cacheable(value = "ai-responses", key = "#prompt", unless = "#result.length() > 1000")
|
|
public String cachedAsk(String prompt) {
|
|
return agentTemplate.ask(prompt);
|
|
}
|
|
```
|
|
|
|
#### 技巧二: 流式响应
|
|
```java
|
|
@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
|
public Flux<ServerSentEvent<String>> streamChat(String message) {
|
|
return agentTemplate.stream(message)
|
|
.map(chunk -> ServerSentEvent.builder(chunk).build());
|
|
}
|
|
```
|
|
|
|
#### 技巧三: 异步处理
|
|
```java
|
|
@Async
|
|
public CompletableFuture<String> asyncAsk(String question) {
|
|
return CompletableFuture.completedFuture(
|
|
agentTemplate.ask(question)
|
|
);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 4 安全与合规
|
|
|
|
### 4.1 数据安全
|
|
```yaml
|
|
app:
|
|
ai:
|
|
safety:
|
|
enabled: true
|
|
block-keywords:
|
|
- 密码
|
|
- token
|
|
- secret
|
|
```
|
|
|
|
### 4.2 审计日志
|
|
```java
|
|
@Component
|
|
public class AiAuditAdvisor implements CallAroundAdvisor {
|
|
|
|
@Override
|
|
public AdvisedResponse aroundCall(AdvisedRequest request, CallAroundAdvisorChain chain) {
|
|
// 记录请求
|
|
auditLog.info("AI请求: user={}, prompt={}",
|
|
getCurrentUser(), request.prompt());
|
|
|
|
AdvisedResponse response = chain.nextAroundCall(request);
|
|
|
|
// 记录响应
|
|
auditLog.info("AI响应: user={}, tokens={}",
|
|
getCurrentUser(), response.metadata().getTokensUsage());
|
|
|
|
return response;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 5. 常见问题解答
|
|
|
|
### Q1: 如何选择合适的模型?
|
|
|
|
**A**:
|
|
- **GPT-4**: 复杂任务、需要高质量输出
|
|
- **GPT-3.5**: 日常对话、成本敏感场景
|
|
- **Ollama(本地)**: 数据敏感、离线环境
|
|
- **通义千问**: 中文场景、国内部署
|
|
|
|
### Q2: Token 费用如何控制?
|
|
|
|
**A**:
|
|
1. 设置 `max-tokens-per-request`
|
|
2. 优化 Prompt,避免冗余
|
|
3. 使用缓存减少重复调用
|
|
4. 监控用量,设置告警
|
|
|
|
### Q3: 如何处理 AI 的错误输出?
|
|
|
|
**A**:
|
|
1. 添加验证逻辑
|
|
2. 使用结构化输出(JSON Schema)
|
|
3. 设置重试机制
|
|
4. 人工审核关键环节
|
|
|
|
### Q4: 生产环境需要注意什么?
|
|
|
|
**A**:
|
|
1. ✅ 配置限流和熔断
|
|
2. ✅ 启用监控和告警
|
|
3. ✅ 做好异常处理
|
|
4. ✅ 定期清理会话数据
|
|
5. ✅ 备份向量数据库
|
|
|
|
---
|
|
|
|
## 6. 总结
|
|
|
|
### 核心要点回顾
|
|
|
|
1. **Spring AI 简化了 AI 应用开发**
|
|
- 统一的抽象层
|
|
- 开箱即用的 Starter
|
|
- 与 Spring 生态完美集成
|
|
|
|
2. **四大核心能力**
|
|
- Agent: 对话交互
|
|
- RAG: 知识增强
|
|
- MCP: 工具调用
|
|
- Graph: 工作流编排
|
|
|
|
3. **企业级特性**
|
|
- 安全防护
|
|
- 限流降级
|
|
- 可观测性
|
|
- 多模型支持
|