基于 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时遇到具体问题,可以随时追问。

相关推荐
小毅&Nora6 小时前
【Spring AI Alibaba】 ⑤ 人工介入(Human-in-the-loop):关键决策点的智能审批与中断恢复
人工智能·spring ai
better_liang5 天前
每日Java面试场景题知识点之-Spring AI企业级AI应用开发
java·面试题·智能客服·ai应用·spring ai·企业级开发
腾飞开源5 天前
53_Spring AI 干货笔记之转录API
人工智能·语音转文字·spring ai·azure openai·转录api·openai whisper·统一接口
Java小生不才9 天前
SAA入门代码
阿里云·spring ai
多则惑少则明9 天前
AI大模型实用(八)Java快速实现智能体整理(使用LangChain4j-agentic来进行情感分析/分类)
java·人工智能·spring ai·langchain4j
小毅&Nora9 天前
【AI微服务】【Spring AI Alibaba】 ④ 深度实战:从零构建通义千问聊天服务(2025 最新版)
人工智能·微服务·spring ai
小毅&Nora10 天前
【AI微服务】【Spring AI Alibaba】 ③ Spring AI Alibaba Agent 核心执行流程源码解析
人工智能·微服务·spring ai
wasteland~11 天前
Spring AI实战:SpringBoot项目结合Spring AI开发——Tool Calling(工具调用)详解与实战
springboot·工具调用·spring ai·tool calling
递归尽头是星辰12 天前
AI 驱动的报表系统:从传统到智能的落地与演进
大数据·人工智能·大模型应用·spring ai·ai 报表·报表智能化