内容
# Spring AI MCP:库存管理系统与 AI 集成
[](https://www.oracle.com/java/technologies/javase-jdk17-downloads.html)
[](https://spring.io/projects/spring-boot)
[](https://spring.io/projects/spring-ai)
[](LICENSE)
## 📚 项目概述
该 Spring Boot 应用展示了一个具有 AI 能力的库存和用户管理系统。它演示了如何通过 Spring AI 集成多个 AI 模型(Google Gemini 和 Anthropic Claude),提供自然语言查询库存和用户数据的能力,并利用 Spring AI 的强大的工具/函数调用功能。
## ✨ 功能特点
- 🤖 基于 Spring AI 的自然语言查询接口
- 📦 完整的库存管理系统
- 👥 用户管理,支持基于角色的访问控制
- 📊 RESTful API,提供全面的 OpenAPI 文档
- 🧠 与多个 AI 模型(Gemini 和 Claude)集成
- 🔄 基于工具的 AI 交互模式
- 🗄️ 使用 H2 内存数据库进行开发
## 🧠 Spring AI:工具/函数调用详解
### 核心概念:什么是函数调用/工具使用?
函数调用(或工具使用)是一种强大的机制,允许大型语言模型(LLMs)请求执行特定的、开发者定义的函数(工具)在您的 Spring 应用中。LLM 不仅可以生成文本,还可以:
* 访问实时数据(例如,库存记录,用户配置文件)
* 与私有或外部 API 交互
* 执行操作(例如,查询数据库,执行业务逻辑)
* 利用模型原本未训练的信息
本质上,它弥合了 LLM 的生成能力与您的应用特定功能或数据源之间的差距。
### Spring AI 实现
Spring AI 提供了抽象和集成,使得在 Spring 应用中实现函数调用变得简单:
1. **定义工具:**
* 工具定义为带有 `@Tool` 注解的标准 Java 方法,位于 Spring 服务类中
* 方法参数可以使用 `@ToolParam` 注解提供描述
* 这些描述帮助 LLM 了解函数的作用和调用时机
2. **使工具可用:**
* 当使用 `ChatClient` 向 LLM 发起 API 调用时,指定哪些工具应该可用
* Spring AI 处理必要的协议细节,以告知底层 LLM 有哪些可用函数
3. **处理 LLM 的函数调用请求:**
* 如果 LLM 确定需要调用提供的函数之一,它将发出调用
* LLM 从对话上下文中提取参数,传递给函数
4. **执行函数:**
* Spring AI 处理请求函数的执行,并提供参数
* 函数在您的应用上下文中执行,完全访问您的服务和仓库
5. **将结果返回给 LLM:**
* 执行函数后,Spring AI 将结果返回给 LLM
* LLM 使用此结果形成对原始用户查询的最终文本响应
### 在 Spring AI 环境中的优势
* **抽象:** 简化与支持函数调用的不同 AI 模型的交互
* **集成:** 利用熟悉的 Spring 概念,如 Bean 和依赖注入
* **能力:** 通过将 LLM 置于您的应用上下文和数据中,大幅扩展其能力
* **一致性:** 确保基于您实际业务数据的可靠、准确的响应
## 🏗️ 架构组件
### 核心 API 层
1. **RESTful 控制器**
- 结构良好的控制器,提供全面的 OpenAPI 文档
- 一致的错误处理和响应模式
- 支持分页和灵活查询
2. **服务层**
- 清晰的关注点分离,基于接口的设计
- 数据完整性的事务边界
- 丰富的验证和异常处理
- 带有 `@Tool` 注解的 AI 集成服务方法
3. **数据实体**
- 具有适当关系的 JPA 实体
- 使用 Jakarta Bean Validation 的验证约束
- 用于跟踪创建和更新的审计字段
### AI 集成
1. **多模型支持**
- Anthropic Claude 集成(`claude-3-5-sonnet-20241022`)
- Google Gemini 集成(`gemini-2.0-flash`)
- 可配置的模型参数(温度,令牌限制)
2. **自然语言接口**
- 库存查询的问答范式
- 用于处理自然语言的 AI 代理服务
- 用于一致的 AI 交互的提示模板系统
3. **基于工具的 AI 访问**
- 用于方法发现的 Spring AI 注解(`@Tool`,`@ToolParam`)
- 作为 AI 工具的领域服务方法
- 动态的数据库查询能力
## 🛠️ 技术实现
### 技术栈
- **Spring Boot**:应用的核心框架
- **Spring AI**:与 AI 服务和工具/函数调用的集成
- **Spring Data JPA**:数据库交互
- **H2 数据库**:用于开发的内存数据库
- **SpringDoc OpenAPI**:API 文档
### 数据库配置
```properties
# 数据源配置
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
# JPA 配置
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
# H2 控制台配置
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
```
### AI 服务配置
```properties
# Google Gemini 配置
spring.ai.openai.chat.base-url=https://generativelanguage.googleapis.com
spring.ai.openai.chat.completions-path=/v1beta/openai/chat/completions
spring.ai.openai.api-key=${GEMINI_AI_API_KEY}
spring.ai.openai.chat.options.model=gemini-2.0-flash
# Anthropic 配置
spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY}
spring.ai.anthropic.chat.options.model=claude-3-5-sonnet-20241022
spring.ai.anthropic.chat.options.temperature=1
spring.ai.anthropic.chat.options.max-tokens=8192
```
## 📊 系统流程图
```mermaid
sequenceDiagram
participant Client
participant Controllers
participant Services
participant Repositories
participant Database
participant AIAgent as AI Agent Service
participant AIModels as External AI Models
%% 标准 API 访问
Client->>Controllers: 1a. API 请求
Controllers->>Services: 2a. 调用业务逻辑
Services->>Repositories: 3a. 数据库操作
Repositories->>Database: 4a. 执行查询
Database-->>Repositories: 5a. 返回数据
Repositories-->>Services: 6a. 返回结果
Services-->>Controllers: 7a. 处理结果
Controllers-->>Client: 8a. 返回 JSON 响应
%% AI 增强查询
Client->>Controllers: 1b. 向 AgentController 提问
Controllers->>AIAgent: 2b. 处理自然语言问题
AIAgent->>AIAgent: 3b. 加载系统和用户模板
AIAgent->>AIModels: 4b. 发送结构化提示
loop 工具使用(函数调用)
AIModels->>AIAgent: 5b. 请求工具执行
AIAgent->>Services: 6b. 调用带有 @Tool 注解的方法
Services->>Repositories: 7b. 执行数据库操作
Repositories->>Database: 8b. 查询数据
Database-->>Repositories: 9b. 返回数据
Repositories-->>Services: 10b. 处理结果
Services-->>AIAgent: 11b. 返回工具结果
AIAgent-->>AIModels: 12b. 提供工具输出
end
AIModels-->>AIAgent: 13b. 生成自然语言响应
AIAgent-->>Controllers: 14b. 格式化响应为答案 DTO
Controllers-->>Client: 15b. 提供 AI 增强响应
```
## 📝 API 端点
### 产品管理
- `GET /api/products` - 获取所有产品(分页)
- `GET /api/products/{id}` - 按 ID 获取产品
- `GET /api/products/sku/{sku}` - 按 SKU 获取产品
- `GET /api/products/category/{categoryId}` - 按类别获取产品
- `GET /api/products/price-range` - 按价格范围获取产品
- `GET /api/products/search` - 按名称搜索产品
- `POST /api/products` - 创建新产品
- `PUT /api/products/{id}` - 更新现有产品
- `DELETE /api/products/{id}` - 删除产品
### 类别管理
- `GET /api/categories` - 获取所有类别(分页)
- `GET /api/categories/{id}` - 按 ID 获取类别
- `GET /api/categories/name/{name}` - 按名称获取类别
- `GET /api/categories/search` - 按名称搜索类别
- `POST /api/categories` - 创建新类别
- `PUT /api/categories/{id}` - 更新现有类别
- `DELETE /api/categories/{id}` - 删除类别
### 用户管理
- `GET /api/users` - 获取所有用户(分页)
- `GET /api/users/{id}` - 按 ID 获取用户
- `GET /api/users/username/{username}` - 按用户名获取用户
- `GET /api/users/email/{email}` - 按邮箱获取用户
- `GET /api/users/role/{role}` - 按角色获取用户
- `POST /api/users/register` - 注册新用户
- `PUT /api/users/{id}` - 更新现有用户
- `DELETE /api/users/{id}` - 删除用户
- `PUT /api/users/{id}/roles` - 为用户添加角色
- `DELETE /api/users/{id}/roles` - 从用户中删除角色
### 身份验证
- `POST /api/auth/register` - 注册新用户
### AI 集成
- `POST /api/agent/question` - 询问关于库存和用户的自然语言问题
## 🧩 关键组件
### AgentService 实现
`AgentServiceImpl` 类是 AI 集成的核心:
```java
@Service
@RequiredArgsConstructor
@Slf4j
public class AgentServiceImpl implements AgentService {
private final CategoryService categoryService;
private final ProductService productService;
private final UserService userService;
private final AgentUtil agentUtil;
@Autowired
@Qualifier("anthropicChatClient")
private ChatClient anthropicChatClient;
@Autowired
@Qualifier("geminiAiChatClient")
private ChatClient geminiChatClient;
// 模板资源
@Value("classpath:templates/ai/system/store/inventory-and-users.structure.st")
private Resource systemSummaryBookTemplate;
@Value("classpath:templates/ai/user/store/inventory-and-users.structure.st")
private Resource userSummaryBookTemplate;
@SneakyThrows
@Override
public Answer getAnswer(Question question) {
if (question == null || question.getText() == null) {
log.error("问题或其文本不能为空。 {}", question);
throw new IllegalArgumentException("问题或其文本不能为空。");
}
ObjectMapper objectMapper = new ObjectMapper();
String questionJson = objectMapper.writeValueAsString(question);
PromptTemplate systemPromptTemplate = new PromptTemplate(this.systemSummaryBookTemplate);
PromptTemplate userPromptTemplate = new PromptTemplate(this.userSummaryBookTemplate);
BeanOutputConverter<Answer> format = new BeanOutputConverter<>(Answer.class);
Prompt systemPrompt = systemPromptTemplate.create();
Prompt userPrompt = userPromptTemplate.create(Map.of("question", questionJson, "format", format.getFormat()));
String aiResponse =
anthropicChatClient.prompt(systemPrompt)
.advisors(new SimpleLoggerAdvisor())
.user(userPrompt.getContents())
.tools(this.agentUtil)
.call().content();
if (aiResponse == null) {
log.error("AI 响应为空,问题: {}", questionJson);
throw new IllegalStateException("AI 响应不能为空。");
}
return format.convert(aiResponse);
}
}
```
### 基于工具的 AI 访问
服务方法通过 `@Tool` 注解暴露给 AI:
```java
@Tool(description = "按类别 ID 查找产品,分页")
public Page<Product> findProductsByCategory(
@ToolParam(description = "要过滤的类别 ID") Long categoryId,
@ToolParam(description = "分页设置") Pageable pageable) {
// 验证类别存在
if (!categoryService.existsById(categoryId)) {
throw new NoSuchElementException("类别未找到,ID: " + categoryId);
}
return productRepository.findByCategoryId(categoryId, pageable);
}
@Tool(description = "检查用户是否存在,按 ID")
public boolean existsById(@ToolParam(description = "要检查的用户 ID") Long id) {
return userRepository.existsById(id);
}
@Tool(description = "执行 SQL 查询,返回数据库中的所有表")
public List<Map<String, Object>> getAllTables() {
String sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PUBLIC'";
return jdbcTemplate.queryForList(sql);
}
```
### 实体关系
核心实体结构具有适当的关联:
```java
@Entity
@Table(name = "products")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank(message = "产品名称必填")
@Column(nullable = false)
private String name;
private String description;
@NotNull(message = "价格必填")
@Positive(message = "价格必须为正数")
@Column(nullable = false)
private BigDecimal price;
@NotBlank(message = "SKU 必填")
@Column(unique = true, nullable = false)
private String sku;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "category_id")
private Category category;
// 审计字段
@CreationTimestamp
@Column(name = "created_at", nullable = false, updatable = false)
private LocalDateTime createdAt;
@UpdateTimestamp
@Column(name = "updated_at")
private LocalDateTime updatedAt;
}
```
## 🚀 快速开始
### 前提条件
- Java 17 或更高版本
- Maven 或 Gradle
- Anthropic Claude 和 Google Gemini 的 API 密钥
### 环境变量
创建 `.env` 文件,包含以下变量:
```
ANTHROPIC_API_KEY=your_anthropic_api_key
GEMINI_AI_API_KEY=your_gemini_api_key
```
### 运行应用程序
1. 克隆仓库
```bash
git clone https://github.com/maxiplux/spring-ai-mcp-tools-and-patterns.git
cd spring-ai-mcp-tools-and-patterns
```
2. 构建项目
```bash
./gradlew build
```
3. 运行应用程序
```bash
./gradlew bootRun
```
4. 访问应用程序
- API 文档:http://localhost:8080/swagger-ui.html
- H2 控制台:http://localhost:8080/h2-console
## 📄 许可证
该项目根据 MIT 许可证授权 - 有关详细信息,请参阅 [LICENSE](LICENSE) 文件。
连接信息
猜你喜欢
暂无推荐服务器