基于 Spring AI 开发智能邮件分类器

基于 Spring AI 开发智能邮件分类器

      • [🏗️ 1. 项目架构与流程](#🏗️ 1. 项目架构与流程)
      • [📦 2. 环境准备与项目初始化](#📦 2. 环境准备与项目初始化)
        • [**1. 确保环境符合要求**](#1. 确保环境符合要求)
        • [**2. 创建Spring Boot项目**](#2. 创建Spring Boot项目)
        • [**3. 添加Spring AI依赖**](#3. 添加Spring AI依赖)
        • [**4. 配置API Key与连接**](#4. 配置API Key与连接)
      • [⚙️ 3. 核心代码实现](#⚙️ 3. 核心代码实现)
        • [**1. 实体类 (定义请求与响应格式)**](#1. 实体类 (定义请求与响应格式))
        • [**2. 服务层 (核心AI交互逻辑)**](#2. 服务层 (核心AI交互逻辑))
        • [**3. 控制层 (暴露REST API)**](#3. 控制层 (暴露REST API))
      • [🧪 4. 运行与测试](#🧪 4. 运行与测试)
      • [🐳 5. 部署上线 (Docker化)](#🐳 5. 部署上线 (Docker化))
        • [**1. 编写 Dockerfile**](#1. 编写 Dockerfile)
        • [**2. 构建镜像并运行**](#2. 构建镜像并运行)
        • [**3. 验证部署**](#3. 验证部署)
      • [💡 深入与进阶方向(体现你的ML优势)](#💡 深入与进阶方向(体现你的ML优势))

将详细介绍如何使用 Spring AI 开发一个完整的智能邮件分类器。这个方案充分利用了Java和Spring Boot经验,并引入了AI能力。

🏗️ 1. 项目架构与流程

下图清晰地展示了本Demo的核心架构和数据流转,它遵循经典的三层架构模式:
Spring Boot 应用
返回分类结果
处理响应
返回JSON
HTTP Client

Postman/浏览器
HTTP请求

含邮件文本
Controller层

EmailController
Service层

EmailClassifyService
Spring AI 抽象层

ChatClient
HTTP 调用
大模型API

如DeepSeek/OpenAI
HTTP响应

分类结果

📦 2. 环境准备与项目初始化

1. 确保环境符合要求
  • Java : 版本 17 或以上 (Spring AI 3.x 要求)。
  • 项目管理工具: Maven 或 Gradle。
  • IDE: 推荐 IntelliJ IDEA。
  • 获取API Key : 访问 DeepSeekOpenAI 平台注册并获取API Key。
2. 创建Spring Boot项目

推荐使用 start.spring.io 快速生成项目,需选择:

  • Project: Maven
  • Language: Java
  • Spring Boot: 3.3.x 版本
  • Dependencies : 添加 Spring WebLombok (简化代码)。
3. 添加Spring AI依赖

在生成项目的 pom.xml 中,手动添加Spring AI的依赖。由于Spring AI未在官方Starter中,需指定其仓库。

关键配置如下:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.4</version> <!-- 确保使用3.x版本 -->
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>email-ai-classifier</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>email-ai-classifier</name>
    <description>智能邮件分类器Demo - Spring Boot + Spring AI</description>

    <properties>
        <java.version>17</java.version>
        <!-- 指定Spring AI版本 -->
        <spring-ai.version>1.0.0-M3</version>
    </properties>

    <repositories>
        <!-- Spring AI 里程碑仓库 -->
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <!-- 中央仓库作为备用 -->
        <repository>
            <id>central</id>
            <url>https://repo1.maven.org/maven2</url>
        </repository>
    </repositories>

    <dependencies>
        <!-- Spring Boot 核心Web starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring AI OpenAI Starter (兼容DeepSeek等OpenAI API格式的模型) -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>

        <!-- 参数验证 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <!-- 开发工具:热部署、Lombok -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- 测试 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
            <!-- 编译使用Java 17 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
4. 配置API Key与连接

src/main/resources/application.yml 中配置。务必注意将API Key放在环境变量中,而非直接写在配置文件里,这是重要的安全实践。

yaml 复制代码
# ========================
# 应用基础配置
# ========================
server:
  port: 8080
  servlet:
    context-path: /
  # 针对可能的大模型响应,适当调整超时时间
  tomcat:
    max-http-form-post-size: 2MB
  # 响应超时设置(毫秒)
  connection-timeout: 30s

spring:
  application:
    name: email-ai-classifier
  
  # ========================
  # Spring AI 配置 (核心)
  # ========================
  ai:
    openai:
      # !!! 安全警告:务必通过环境变量配置API Key !!!
      # 在运行环境设置:DEEPSEEK_API_KEY 或 OPENAI_API_KEY
      api-key: ${AI_API_KEY:} # 默认值为空,强制从环境变量获取
      
      # 国内模型DeepSeek专用端点(如果使用OpenAI官方服务,则删除此配置)
      base-url: https://api.deepseek.com
      
      # 聊天模型通用配置
      chat:
        options:
          # 模型名称:
          # - DeepSeek: deepseek-chat 或 deepseek-reasoner
          # - OpenAI: gpt-3.5-turbo, gpt-4, gpt-4o-mini等
          model: deepseek-chat
          
          # 温度值:控制随机性 (0.0-2.0),分类任务建议较低值
          temperature: 0.1
          
          # 最大输出token数
          max-tokens: 500
          
          # 开启JSON格式输出(如果模型支持)
          # response-format: { type: "json_object" }
        
        # HTTP客户端配置
        client:
          connect-timeout: 10s    # 连接超时
          read-timeout: 30s       # 读取超时(大模型响应可能较慢)
  
  # ========================
  # 日志配置(便于调试)
  # ========================
  output:
    ansi:
      enabled: ALWAYS  # 启用彩色日志,便于阅读

logging:
  level:
    root: INFO
    com.example: DEBUG          # 你的项目包名
    org.springframework.ai: DEBUG  # 查看Spring AI详细日志
    org.springframework.web: DEBUG
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} - %highlight(%-5level) [%thread] %cyan(%logger{36}) - %msg%n"

# ========================
# 自定义应用配置
# ========================
app:
  classifier:
    # 支持的分类类别(与Prompt中保持一致)
    categories: ["产品咨询", "售后服务", "商务合作", "投诉反馈", "垃圾推广"]
    # 是否启用缓存(后续扩展)
    cache-enabled: false
    # 最大邮件内容长度(字符)
    max-content-length: 5000

# ========================
# 生产环境可选配置(部署时考虑)
# ========================
---
# 多环境配置示例:生产环境配置
# 通过启动参数激活:--spring.profiles.active=prod
spring:
  config:
    activate:
      on-profile: prod
  
  ai:
    openai:
      chat:
        client:
          # 生产环境更长的超时设置
          read-timeout: 60s
  
  # 生产环境日志级别调高
logging:
  level:
    root: WARN
    com.example: INFO
    org.springframework.ai: INFO

在启动应用前,设置环境变量:

  • Linux/Mac : export DEEPSEEK_API_KEY=your_api_key_here
  • Windows (CMD) : set DEEPSEEK_API_KEY=your_api_key_here
  • 在IDEA中 :可通过 Run/Debug ConfigurationsEnvironment variables 字段添加。

⚙️ 3. 核心代码实现

1. 实体类 (定义请求与响应格式)

创建 EmailClassificationRequest.javaEmailClassificationResponse.java

java 复制代码
// EmailClassificationRequest.java
import lombok.Data;

@Data
public class EmailClassificationRequest {
    private String emailContent;
    private String sender; // 可选字段,用于未来扩展
}
java 复制代码
// EmailClassificationResponse.java
import lombok.Data;

@Data
public class EmailClassificationResponse {
    private String originalContent;
    private String category; // 如:"咨询"、"投诉"
    private String reasoning; // AI做出此分类的简要原因,便于调试
    private Long timestamp;
}
2. 服务层 (核心AI交互逻辑)

创建 EmailClassifyService.java。这里是Prompt工程的核心,你机器学习背景的价值在此体现:设计出让AI稳定、准确输出的提示词。

java 复制代码
// EmailClassifyService.java
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
import java.time.Instant;

@Service
@Slf4j
public class EmailClassifyService {

    private final ChatClient chatClient;

    // 通过构造器注入ChatClient
    public EmailClassifyService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    public EmailClassificationResponse classifyEmail(EmailClassificationRequest request) {
        // 1. 构造精确的Prompt - 这是分类准确的关键
        String systemPrompt = """
                你是一个专业的邮件分类AI助手。请严格按照以下规则对用户提供的邮件内容进行分类:
                1. **类别列表**:仅限【产品咨询】、【售后服务】、【商务合作】、【投诉反馈】、【垃圾推广】。
                2. **输出格式**:你必须以严格的JSON格式回答,且只包含以下两个字段:
                    - "category": 字符串,必须是上述五个类别之一。
                    - "reasoning": 字符串,用一句话中文解释分类依据。
                3. **分类逻辑**:
                    - 询问功能、价格、规格的,归为【产品咨询】。
                    - 寻求维修、退换货、使用帮助的,归为【售后服务】。
                    - 提及合作、采购、联盟的,归为【商务合作】。
                    - 表达不满、要求赔偿、批评服务的,归为【投诉反馈】。
                    - 广告、推销、明显无关内容的,归为【垃圾推广】。
                请确保判断基于邮件主旨,不要自行臆断。
                """;

        // 2. 调用AI
        String aiJsonResponse = chatClient.prompt()
                .system(systemPrompt) // 设定系统角色和规则
                .user("请分类此邮件内容:" + request.getEmailContent()) // 用户输入
                .call() // 执行调用
                .content(); // 获取文本响应

        log.info("AI原始响应: {}", aiJsonResponse);

        // 3. 解析AI的JSON响应 (生产环境建议用Jackson/ObjectMapper)
        // 此处为简化示例,实际解析需处理异常
        String category = extractFromJson(aiJsonResponse, "category");
        String reasoning = extractFromJson(aiJsonResponse, "reasoning");

        // 4. 构建返回对象
        EmailClassificationResponse response = new EmailClassificationResponse();
        response.setOriginalContent(request.getEmailContent());
        response.setCategory(category);
        response.setReasoning(reasoning);
        response.setTimestamp(Instant.now().toEpochMilli());

        return response;
    }

    // 简单的JSON解析工具方法(仅用于Demo,生产环境请使用标准库)
    private String extractFromJson(String json, String key) {
        // 示例:简单查找 "category": "产品咨询" 这样的模式
        String pattern = "\"" + key + "\":\\s*\"([^\"]+)\"";
        java.util.regex.Pattern r = java.util.regex.Pattern.compile(pattern);
        java.util.regex.Matcher m = r.matcher(json);
        if (m.find()) {
            return m.group(1);
        }
        return "解析失败";
    }
}
3. 控制层 (暴露REST API)

创建 EmailClassificationController.java

java 复制代码
// EmailClassificationController.java
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;

@RestController
@RequestMapping("/api/email")
@Slf4j
public class EmailClassificationController {

    private final EmailClassifyService classifyService;

    public EmailClassificationController(EmailClassifyService classifyService) {
        this.classifyService = classifyService;
    }

    @PostMapping("/classify")
    public EmailClassificationResponse classify(@Valid @RequestBody EmailClassificationRequest request) {
        log.info("收到分类请求,发件人: {}, 内容长度: {}", 
                 request.getSender(), 
                 request.getEmailContent().length());
        return classifyService.classifyEmail(request);
    }

    // 一个简单的健康检查接口,用于验证服务是否启动
    @GetMapping("/health")
    public String health() {
        return "Email Classification Service is up!";
    }
}

🧪 4. 运行与测试

  1. 启动应用 :运行 Application 主类。看到 Started Application 日志即成功。

  2. 健康检查 :浏览器访问 http://localhost:8080/api/email/health

  3. 功能测试 :使用 PostmancURL 测试分类接口。

    bash 复制代码
    curl -X POST http://localhost:8080/api/email/classify \
    -H "Content-Type: application/json" \
    -d '{
        "emailContent": "你好,这款产品的保修期是多久?如果坏了怎么维修?",
        "sender": "customer@example.com"
    }'

    预期响应:

    json 复制代码
    {
        "originalContent": "你好,这款产品的保修期是多久?如果坏了怎么维修?",
        "category": "产品咨询",
        "reasoning": "邮件内容涉及产品保修和维修询问,符合产品咨询特征。",
        "timestamp": 1743225600000
    }

🐳 5. 部署上线 (Docker化)

1. 编写 Dockerfile

在项目根目录创建 Dockerfile

dockerfile 复制代码
# 使用轻量级JDK运行时镜像
FROM openjdk:17-jdk-slim AS builder
# 将Maven包装器复制到容器中
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
# 下载依赖(利用Docker缓存层,加速构建)
RUN ./mvnw dependency:go-offline

# 复制源代码并打包
COPY src ./src
RUN ./mvnw clean package -DskipTests

# 运行时阶段,使用更小的JRE镜像
FROM openjdk:17-jre-slim
# 将上阶段打包好的jar包复制过来
COPY --from=builder target/*.jar app.jar
# 暴露Spring Boot默认端口
EXPOSE 8080
# 设置JVM参数,优化容器内运行体验
ENTRYPOINT ["java", "-jar", "/app.jar"]
2. 构建镜像并运行
bash 复制代码
# 1. 在项目根目录(Dockerfile所在目录)构建镜像
docker build -t email-ai-classifier .

# 2. 运行容器,将宿主机的8080端口映射到容器的8080端口,并传递API Key环境变量
docker run -d -p 8080:8080 \
  --name email-classifier \
  -e DEEPSEEK_API_KEY="你的实际API密钥" \
  email-ai-classifier
3. 验证部署

访问 http://你的服务器IP:8080/api/email/health,看到成功信息即表示服务已在云端运行。

💡 深入与进阶方向(体现你的ML优势)

完成以上基础Demo后,你可以利用你的机器学习背景进行深度扩展:

  1. 高级Prompt工程

    • 实现 Few-shot Learning,在Prompt中提供几个高质量的分类示例。
    • 要求AI输出置信度分数,对低置信度的结果进行人工复核流程设计。
  2. 引入向量数据库(RAG)

    • 将历史邮件和分类规则存入 ChromaDBMilvus
    • 在调用大模型前,先检索相似历史案例,将结果作为上下文注入Prompt,使分类更精准、更符合业务历史。
  3. 构建分类评估体系

    • 创建测试集,编写脚本批量调用接口,计算分类的准确率、召回率
    • 对比不同Prompt策略或不同模型(如DeepSeek vs GPT-3.5)在你这特定任务上的性能,形成实验报告。

这个项目完全在你的技术射程之内。如果在配置依赖、编写Dockerfile或设计更复杂的Prompt时遇到具体问题,可以随时追问。

相关推荐
还是鼠鼠3 天前
Spring AI ChatClient详解:创建第一个AI客户端
java·springboot·spring ai·chatclient
还是鼠鼠4 天前
Spring AI连接DeepSeek与通义千问:application.yaml配置详解
java·通义千问·spring ai·deepseek
中间件XL4 天前
ai-agent框架spring ai/alibaba 原理源码分析(十)沙箱
沙箱·ai agent·智能体·spring ai·spring ai graph
还是鼠鼠6 天前
【Spring AI智能体实战 02】Spring Boot 3.4整合Spring AI:项目创建与依赖配置
java·人工智能·spring boot·maven·spring ai
还是鼠鼠7 天前
【Spring AI智能体实战 01】Java开发者接入大模型:国内平台、Token与API Key入门
java·大模型·spring ai·deepseek·阿里云百炼
默辨9 天前
Spring AI Alibaba 核心知识点
java·ai·spring ai·spring alibaba
Muscleheng13 天前
Spring Boot 3.x 集成 DeepSeek 实现 Function Calling(工具调用)
人工智能·spring boot·后端·ai·spring ai·deepseek
佛祖让我来巡山13 天前
SpringAI保姆级实战教程
spring ai·springai·springai教程·springai入门
BerryS3N13 天前
Java 后端转型大模型:Demo 能跑不等于能上线
java·人工智能·python·java后端·spring ai·langchain4j·大模型转型
lichuangcsdn15 天前
【Spring AI 学习(三)】实现简单的对话
java·人工智能·学习·spring·spring ai