课程0基础Agent开发课 / 框架与平台对比 / Spring-AI入门-Java开发者的AI落地捷径
— 12 min read

Spring-AI入门-Java开发者的AI落地捷径

对于基于 Spring Boot 构建的系统,如果需要在现有服务中集成 AI 问答功能,通常面临两种方案的选择:

Spring AI 入门:Java 开发者的 AI 落地捷径

对于基于 Spring Boot 构建的系统,如果需要在现有服务中集成 AI 问答功能,通常面临两种方案的选择:

方案一: 引入 Python 服务,使用 LangChain 或 LlamaIndex 实现 AI 能力,通过 HTTP 或 RPC(远程过程调用:让一个服务直接调用另一个服务的函数,就像调用本地函数一样)与 Java 服务通信。这条路可行,但代价明显——Python 服务需要单独维护,增加一套部署流程,跨语言排查问题成本高,团队需要同时具备两个技术栈的运维能力。

方案二: 使用 Spring AI。Spring 官方出品,与 Spring Boot 原生集成,用 Java 编写,无需引入新语言,对现有 Java 团队几乎没有额外学习成本。

本文以方案二为主线,介绍 Spring AI 的核心概念、快速上手步骤、RAG 实现,以及与 Python 框架的对比。

1. Spring AI 是什么

Spring AI架构图
Spring AI 架构 — 核心组件与 Spring Boot 生态集成

Spring AI 不是一个大模型,而是一个调用各种 AI 服务的统一接口,是 Spring 生态针对 AI 应用开发的官方解决方案。

它的作用与 LangChain 类似:将不同 AI 服务商(OpenAI、Anthropic、Azure OpenAI、Ollama 本地模型等)的 API 统一封装,使得切换模型时无需修改业务代码。同时提供 RAG、Function Calling、流式输出等常用能力的标准实现。

与 Spring Boot 的整合是原生的——@Autowired 注入,application.yml 配置,与编写普通 Spring 服务没有区别。

2. 核心组件

ChatClient:调用 LLM 的统一接口。无论底层是 OpenAI 还是 Anthropic,上层代码保持一致,切换模型只需修改配置。

EmbeddingModel:将文本转换为向量(Embedding,嵌入:把文字转成一串数字,让计算机能计算文本之间的相似度),用于 RAG 场景下的语义检索。

VectorStore:向量数据库(专门存储向量数据并支持高效相似度搜索的数据库)的统一接口,支持 PgVector、Redis、Milvus、Weaviate、Chroma 等。

DocumentReader:文档加载器,支持 PDF、Word、HTML、Markdown、JSON、数据库等各类来源。

3. 快速入门

第一步,添加依赖。 Spring AI 目前需要 Spring Boot 3.x 和 Java 17+(具体版本要求请查阅 Spring AI 官方文档,以下 BOM 版本仅供参考)。

xml
<!-- pom.xml -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>1.0.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- OpenAI 支持 -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    </dependency>
</dependencies>

第二步,配置。

yaml
# application.yml
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      base-url: https://api.openai.com  # 国内可替换为代理地址
      chat:
        options:
          model: gpt-4o-mini
          temperature: 0.7

第三步,实现一个最基础的对话接口。

java
@RestController
@RequestMapping("/ai")
public class ChatController {

    private final ChatClient chatClient;

    public ChatController(ChatClient.Builder builder) {
        this.chatClient = builder
            .defaultSystem("你是一个专业的客服助手,请用简洁友好的语气回答问题。")
            .build();
    }

    @GetMapping("/chat")
    public String chat(@RequestParam String message) {
        return chatClient.prompt()
            .user(message)
            .call()
            .content();
    }
}

完成以上三步后,启动服务,访问 /ai/chat?message=你好,即可收到 AI 的回复。

流式输出。 对话内容较长时,用流式输出让用户边看边等,比等全部生成完再显示体验好得多。

java
@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chatStream(@RequestParam String message) {
    return chatClient.prompt()
        .user(message)
        .stream()
        .content();
}

前端使用 EventSource(浏览器内置 API,用于接收服务端推送的实时事件流)接收,逐字显示,效果与 ChatGPT 的流式输出一致。

4. RAG 实现

RAG(检索增强生成)是 Spring AI 最常用的场景。将企业内部文档(产品手册、FAQ、政策文件)向量化存储,用户提问时先检索相关内容,再让 LLM 基于检索结果生成答案。

添加依赖:

xml
<!-- PgVector 向量存储(PostgreSQL 的向量搜索扩展,让关系型数据库也能存储和检索向量) -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId>
</dependency>
<!-- PDF 文档读取 -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-pdf-document-reader</artifactId>
</dependency>

配置:

yaml
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: postgres
    password: password
  ai:
    vectorstore:
      pgvector:
        initialize-schema: true  # 自动建表
        dimensions: 1536         # OpenAI embedding 维度

文档入库:

java
@Service
public class DocumentIngestionService {

    private final VectorStore vectorStore;

    public DocumentIngestionService(VectorStore vectorStore) {
        this.vectorStore = vectorStore;
    }

    public void ingestPdf(String filePath) {
        // 1. 读取 PDF
        Resource resource = new FileSystemResource(filePath);
        PagePdfDocumentReader pdfReader = new PagePdfDocumentReader(resource);
        List<Document> documents = pdfReader.get();

        // 2. 切块(每块 500 token,重叠 100 token)
        TokenTextSplitter splitter = new TokenTextSplitter(500, 100, 5, 10000, true);
        List<Document> chunks = splitter.apply(documents);

        // 3. 向量化并存入 PgVector(自动调用 Embedding API)
        vectorStore.add(chunks);

        System.out.println("入库完成,共 " + chunks.size() + " 个文本块");
    }
}

查询时检索并生成答案:

java
@RestController
@RequestMapping("/ai")
public class RagController {

    private final ChatClient chatClient;
    private final VectorStore vectorStore;

    public RagController(ChatClient.Builder builder, VectorStore vectorStore) {
        this.vectorStore = vectorStore;
        this.chatClient = builder.build();
    }

    @GetMapping("/rag")
    public String ragQuery(@RequestParam String question) {
        // 1. 检索相关文档块
        List<Document> relevantDocs = vectorStore.similaritySearch(
            SearchRequest.query(question).withTopK(3)
        );

        // 2. 把检索结果拼成上下文
        String context = relevantDocs.stream()
            .map(Document::getContent)
            .collect(Collectors.joining("\n\n"));

        // 3. 带上下文调用 LLM
        String systemPrompt = """
            你是一个专业的问答助手。请仅根据以下提供的资料回答问题。
            如果资料中没有相关信息,请回答"我没有找到相关信息"。

            参考资料:
            {context}
            """;

        return chatClient.prompt()
            .system(s -> s.param("context", context))
            .user(question)
            .call()
            .content();
    }
}

Spring AI 还提供了更高级的 QuestionAnswerAdvisor,可以自动完成检索和生成的完整流程,省去手动拼接的步骤。上面的手动实现方式有助于理解 RAG 的内部逻辑,在实际项目中可根据需求选择更简洁的封装。

5. Function Calling

Function Calling(函数调用:LLM 原生具备的能力,能识别何时需要调用外部工具,并输出结构化的调用指令)使 LLM 能够调用开发者定义的 Java 方法,是实现真正 Agent 能力的基础。

java
// 1. 定义工具函数
@Bean
@Description("查询指定城市的当前天气")
public Function<WeatherRequest, WeatherResponse> weatherFunction() {
    return request -> {
        // 调用真实的天气 API 或数据库
        String weather = queryWeatherApi(request.city());
        return new WeatherResponse(request.city(), weather, "28°C");
    };
}

// 请求/响应类
record WeatherRequest(String city) {}
record WeatherResponse(String city, String condition, String temperature) {}

// 2. 注册工具并调用
@GetMapping("/agent")
public String agentChat(@RequestParam String message) {
    return chatClient.prompt()
        .user(message)
        .functions("weatherFunction")  // 注册工具
        .call()
        .content();
}

当用户询问"北京今天天气怎么样"时,LLM 会自动识别需要调用 weatherFunction,传入参数 {"city": "北京"},获取结果后组织成自然语言回答。整个过程对用户透明。

6. Spring AI vs Python 框架

Spring AI 的优势:

  • 无需切换语言,Java 团队零成本上手
  • 与 Spring Boot 生态完全融合,事务、权限、监控等能力开箱即用
  • 类型安全,编译期即可发现大量潜在问题
  • 部署和运维与现有服务保持一致,不增加额外复杂度

Python 框架(LangChain、LlamaIndex)的优势:

  • 生态更成熟,各类模型和工具的集成覆盖更全
  • 前沿特性更新更快,新出的能力 Python 版本往往优先支持
  • RAG 功能更丰富,LlamaIndex 的索引类型远多于 Spring AI
  • AI/ML 工具链大多属于 Python 生态,配合使用更流畅

选型建议:

Java 团队给现有系统加 AI 功能,Spring AI 是直接的选择——不引入新语言,不增加运维复杂度,功能够用。

想深入 AI 领域、跟进前沿进展,或者新项目没有语言限制,Python 是绕不开的。论文复现、开源工具、新框架,大多数都以 Python 为首。

两者不冲突。Spring AI 处理现有 Java 项目的集成,Python 处理需要深入的部分。

本页目录