最近在尝试将AI能力集成到Java应用中时,发现市面上针对Java开发者的AI应用开发框架选择不多,且配置复杂。Spring AI的出现,特别是其与阿里云等国内服务的集成,为Java开发者提供了一条开箱即用的捷径。本文将手把手带你从零开始,基于Spring AI Alibaba构建一个完整的AI应用,涵盖环境搭建、核心概念、代码实战、常见问题及生产级最佳实践,无论你是刚接触AI的Java开发者,还是希望快速落地AI能力的技术团队,都能从中获得一套可直接复用的解决方案。

1. Spring AI Alibaba 背景与核心概念

在深入代码之前,我们有必要理解Spring AI是什么,以及它如何与Alibaba生态结合,这能帮助我们在后续开发中做出更合理的技术决策。

1.1 什么是Spring AI?

Spring AI是一个由Spring官方社区孵化的项目,旨在将生成式人工智能(Generative AI)能力无缝集成到Spring应用程序中。它的核心目标是为Java开发者提供一个抽象层,屏蔽不同AI服务提供商(如OpenAI、Azure OpenAI、Anthropic、阿里云百炼等)在API调用、参数格式、响应解析等方面的差异。你可以把它想象成Spring Data对数据库操作的抽象,或者Spring Cloud对微服务治理的抽象,只不过这次抽象的对象是AI大模型。

它解决了什么问题?

  1. 供应商锁定 :应用代码不直接依赖某一家AI服务商的SDK,通过更换配置即可切换底层模型提供商。
  2. 开发复杂度 :统一了Prompt构建、模型调用、流式响应处理、上下文管理等通用模式,开发者只需关注业务逻辑。
  3. Spring生态集成 :天然支持Spring Boot的自动配置、依赖注入、外部化配置(application.yml)、Actuator监控等特性,与现有Spring技术栈无缝融合。

1.2 Spring AI Alibaba 是什么?

“Spring AI Alibaba”并非一个独立的官方项目名称,而是指Spring AI框架与阿里巴巴云智能集团提供的AI服务进行集成的实践。目前,Spring AI官方通过 spring-ai-alibaba 模块(或相关starter)提供了对阿里云百炼平台(Model Studio)上多种大语言模型(LLM)和嵌入模型(Embedding Model)的支持。

阿里云百炼 是一个企业级大模型服务平台,提供了通义千问系列等多种模型。通过Spring AI接入,开发者可以使用统一的 ChatClient EmbeddingClient 等接口来调用这些模型,而无需直接处理阿里云API的签名、鉴权等底层细节。

核心价值

  • 合规与可控 :对于国内企业和开发者,使用国内云服务商的AI模型,在数据合规、网络延迟、服务稳定性方面更有保障。
  • 开箱即用 :Spring Boot的“约定大于配置”理念得以延续,只需添加依赖、配置API Key和端点,即可开始调用AI模型。
  • 统一编程模型 :无论后端连接的是OpenAI的GPT还是阿里云的通义千问,你的业务代码(如服务层、控制器层)几乎不需要改动。

1.3 核心组件与抽象

理解以下几个关键接口和概念,是高效使用Spring AI的基础:

  1. ChatClient :聊天客户端,用于与大语言模型进行对话交互。这是最常用的接口。
  2. Prompt :表示发送给模型的请求,通常包含一个或多个 Message 对象。
  3. Message :代表对话中的一条消息,有系统消息( SystemMessage )、用户消息( UserMessage )、助手消息( AssistantMessage )等类型。
  4. ChatResponse :模型调用后返回的响应,其中包含模型生成的 AssistantMessage
  5. EmbeddingClient :嵌入客户端,用于将文本转换为高维向量(Embedding),常用于检索增强生成(RAG)应用。
  6. VectorStore :向量存储抽象,用于存储和检索 Embedding ,Spring AI支持PgVector、Redis、Milvus等多种实现。
  7. AiStream ResponseEntity<Flux<T>> :用于处理模型的流式响应,实现打字机效果,提升用户体验。

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

我们将创建一个标准的Spring Boot 3.x项目,并集成Spring AI Alibaba相关依赖。

2.1 基础环境要求

  • JDK : 17 或更高版本(Spring Boot 3.x 要求)
  • 构建工具 : Maven 3.6+ 或 Gradle 7.x+
  • IDE : IntelliJ IDEA, VS Code, Eclipse等(推荐使用IntelliJ IDEA,其对Spring Boot支持最好)
  • 阿里云账号 : 需要开通百炼平台服务,并获取API Key(下文会详细说明)。

2.2 创建Spring Boot项目

使用 Spring Initializr 或IDE的创建向导,生成一个项目。

关键依赖选择

  • Project : Maven
  • Language : Java
  • Spring Boot : 3.2.5 (建议选择当前稳定版本)
  • Packaging : Jar
  • Java : 17
  • Dependencies :
    • Spring Web - 用于构建RESTful API。
    • Lombok - 简化Java Bean代码(可选,但推荐)。
    • Spring AI - 这是总依赖。在Initializr中可能尚未收录,我们可以手动添加。

2.3 手动添加Spring AI Alibaba依赖

由于Spring AI Alibaba的依赖可能不在Initializr默认列表中,我们需要在创建项目后,手动修改 pom.xml 文件。

首先,添加Spring AI的BOM(Bill of Materials)来统一管理所有Spring AI模块的版本。

<!-- 在 pom.xml 的 <project> 标签下添加 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>0.8.1</version> <!-- 请检查并使用最新稳定版 -->
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

然后,在 <dependencies> 部分添加具体的starter依赖。要使用阿里云百炼,我们需要添加对应的连接器。

<dependencies>
    <!-- Spring Boot 基础依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </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>

    <!-- Spring AI Alibaba 百炼 Starter -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-alibaba-bailian-spring-boot-starter</artifactId>
    </dependency>

    <!-- 如果你还需要使用Embedding等功能,可能需要添加其他starter,如Ollama(本地测试用) -->
    <!-- <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
    </dependency> -->
</dependencies>

版本说明 :Spring AI版本迭代较快,请务必访问 Spring AI官方文档 GitHub仓库 查看最新稳定版本。本文基于 0.8.1 版本编写,核心概念和API基本稳定。

2.4 获取阿里云百炼API密钥

  1. 登录 阿里云官网
  2. 进入 百炼 控制台(产品全称:模型服务平台灵积)。
  3. 在左侧菜单找到 API-KEY管理
  4. 创建一个新的API Key,并妥善保存。你会得到类似 sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 的密钥。
  5. 同时,你还需要知道服务的 Endpoint (端点地址)。通常格式为: https://dashscope.aliyuncs.com/compatible-mode/v1 。具体地址请以百炼平台官方文档为准。

3. 核心配置与第一个AI对话应用

配置是连接Spring AI和阿里云服务的关键一步。

3.1 配置application.yml

src/main/resources/application.yml 文件中,添加Spring AI Alibaba的配置。

spring:
  application:
    name: spring-ai-alibaba-demo

  ai:
    # 配置阿里云百炼
    alibaba:
      bailian:
        # 从百炼控制台获取的API Key
        api-key: sk-你的实际API-KEY
        # 百炼服务的端点地址
        base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
        # 默认使用的聊天模型,例如通义千问Max
        chat:
          options:
            model: qwen-max
            temperature: 0.7 # 创造性,0-2之间,越高越随机
            max-tokens: 2000 # 最大输出token数

# 可选:开启Actuator端点,查看AI相关的健康信息和指标
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,ai

配置项详解

  • spring.ai.alibaba.bailian.api-key : 必填,你的身份凭证。
  • spring.ai.alibaba.bailian.base-url : 必填,服务地址。注意 /compatible-mode/v1 路径是为了兼容OpenAI API格式,方便Spring AI调用。
  • spring.ai.alibaba.bailian.chat.options.model : 指定默认使用的模型。百炼平台提供多个模型,如 qwen-max (通义千问Max)、 qwen-plus qwen-turbo 等,请根据你的需求和服务开通情况选择。
  • temperature : 采样温度,控制输出的随机性。值越低(如0.1),输出越确定、保守;值越高(如1.0),输出越多样、有创意。根据任务类型调整。
  • max-tokens : 限制模型单次响应的最大长度。设置此值可以控制成本并防止生成过长内容。

安全提示 :永远不要将真实的 api-key 提交到代码仓库。在生产环境中,应使用环境变量、配置中心(如Nacos、Apollo)或云厂商的密钥管理服务来注入这些敏感信息。例如:

api-key: ${ALIBABA_BAILIAN_API_KEY:}

然后在启动应用时设置环境变量 ALIBABA_BAILIAN_API_KEY

3.2 创建聊天服务

接下来,我们创建一个Spring Service来封装AI对话逻辑。

// 文件路径:src/main/java/com/example/demo/service/AiChatService.java
package com.example.demo.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
@RequiredArgsConstructor
public class AiChatService {

    // 注入Spring AI自动配置的ChatClient
    private final ChatClient chatClient;

    /**
     * 简单的单轮对话
     * @param userMessage 用户输入的问题
     * @return 模型的回答
     */
    public String simpleChat(String userMessage) {
        log.info("用户提问: {}", userMessage);
        // 方式1:使用ChatClient的fluent API(推荐,更简洁)
        String response = chatClient.prompt()
                .user(userMessage)
                .call()
                .content();
        log.info("模型回答: {}", response);
        return response;
    }

    /**
     * 带系统指令的对话(更可控)
     * @param userMessage 用户问题
     * @return 模型的回答
     */
    public String chatWithSystemPrompt(String userMessage) {
        // 定义系统指令,约束模型的行为
        String systemText = """
                你是一个专业的Java技术专家,擅长用简洁、准确的语言回答Spring框架和AI相关的问题。
                如果用户的问题超出这个范围,请礼貌地告知。
                你的回答需要结构清晰,必要时使用列表或代码示例。
                """;

        // 构建Prompt,包含系统消息和用户消息
        Prompt prompt = new Prompt(
                List.of(
                        new SystemPromptTemplate(systemText).createMessage(), // 系统消息
                        new UserMessage(userMessage) // 用户消息
                )
        );

        // 调用模型
        ChatResponse chatResponse = chatClient.call(prompt);
        String response = chatResponse.getResult().getOutput().getContent();
        log.info("带系统指令的对话回答: {}", response);
        return response;
    }

    /**
     * 使用参数化系统提示词
     * @param userMessage 用户问题
     * @param role 为模型设定的角色
     * @return 模型的回答
     */
    public String chatWithDynamicRole(String userMessage, String role) {
        // 使用模板,动态插入角色信息
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate("""
                你是一个{role}。请根据你作为{role}的专业知识来回答用户的问题。
                回答要体现专业性和针对性。
                """);

        Message systemMessage = systemPromptTemplate.createMessage(Map.of("role", role));
        Prompt prompt = new Prompt(List.of(systemMessage, new UserMessage(userMessage)));

        return chatClient.call(prompt).getResult().getOutput().getContent();
    }
}

代码解析

  1. @RequiredArgsConstructor 是Lombok注解,为 final 字段 chatClient 生成构造函数,实现依赖注入。
  2. ChatClient 是Spring AI的核心接口,Spring Boot会根据 application.yml 的配置,自动为我们创建一个连接到阿里云百炼的 ChatClient Bean。
  3. simpleChat 方法展示了最简洁的调用方式: chatClient.prompt().user(...).call().content()
  4. chatWithSystemPrompt 方法展示了如何添加 SystemMessage 来引导模型行为,这对于提升回答质量和安全性至关重要。
  5. SystemPromptTemplate 允许我们创建带占位符的模板,使系统指令更灵活。

3.3 创建REST控制器

创建一个简单的Controller来暴露HTTP API。

// 文件路径:src/main/java/com/example/demo/controller/ChatController.java
package com.example.demo.controller;

import com.example.demo.service.AiChatService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

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

    private final AiChatService aiChatService;

    @PostMapping("/chat")
    public String chat(@RequestParam String message) {
        return aiChatService.simpleChat(message);
    }

    @PostMapping("/chat/system")
    public String chatWithSystem(@RequestParam String message) {
        return aiChatService.chatWithSystemPrompt(message);
    }

    @PostMapping("/chat/role")
    public String chatWithRole(@RequestParam String message,
                               @RequestParam(defaultValue = "技术文档编写助手") String role) {
        return aiChatService.chatWithDynamicRole(message, role);
    }
}

3.4 运行与测试

  1. 启动Spring Boot应用。
  2. 使用 curl 、Postman或浏览器插件进行测试。

测试简单对话

curl -X POST "http://localhost:8080/api/ai/chat?message=用Java写一个Hello World程序"

测试带系统指令的对话

curl -X POST "http://localhost:8080/api/ai/chat/system?message=解释一下Spring Bean的生命周期"

测试动态角色对话

curl -X POST "http://localhost:8080/api/ai/chat/role?message=分析一下新能源汽车行业的现状&role=行业分析师"

如果一切配置正确,你将收到来自阿里云通义千问模型的JSON格式响应(Spring AI已自动处理,我们得到的是纯文本内容)。

4. 进阶功能实战

掌握了基础对话后,我们探索Spring AI更强大的功能。

4.1 流式响应(Streaming)

流式响应允许模型一边生成,我们一边接收,非常适合需要实时显示的场景(如聊天界面)。Spring AI对此有很好的支持。

// 在 AiChatService 中添加方法
import org.springframework.ai.chat.client.fluent.Response;
import reactor.core.publisher.Flux;
import java.util.concurrent.atomic.AtomicReference;

public Flux<String> streamChat(String userMessage) {
    log.info("开始流式对话,用户提问: {}", userMessage);

    // 使用ChatClient的流式调用
    Response<ChatResponse> response = chatClient.prompt()
            .user(userMessage)
            .stream()
            .call();

    // 将ChatResponse的Flux转换为字符串内容的Flux
    return response.content()
            .map(chunk -> {
                // chunk是流式返回的每一块内容
                String content = chunk;
                log.debug("收到流式块: {}", content);
                return content;
            });
}
// 在 ChatController 中添加新的端点
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import reactor.core.publisher.Flux;

@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamChat(@RequestParam String message) {
    return aiChatService.streamChat(message);
}

测试流式接口 : 可以使用支持Server-Sent Events (SSE)的客户端进行测试,如浏览器EventSource或 curl

curl -N http://localhost:8080/api/ai/chat/stream?message=用一百字介绍Spring AI

你会看到回答内容以数据流的形式逐步返回。

4.2 使用EmbeddingClient和向量数据库(RAG雏形)

检索增强生成(RAG)是当前AI应用的热点。Spring AI提供了 EmbeddingClient VectorStore 抽象。这里我们以简单的内存向量存储 InMemoryVectorStore 为例,演示如何将本地知识库向量化并用于问答。

首先,添加相关依赖(如果使用Ollama本地运行嵌入模型做测试):

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>

并在 application.yml 中配置Ollama(假设本地运行了Ollama服务):

spring:
  ai:
    ollama:
      base-url: http://localhost:11434
      embedding:
        options:
          model: nomic-embed-text # 或其它嵌入模型

然后,创建RAG服务:

// 文件路径:src/main/java/com/example/demo/service/SimpleRagService.java
package com.example.demo.service;

import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingClient;
import org.springframework.ai.reader.TextReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.InMemoryVectorStore;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
@Slf4j
@RequiredArgsConstructor
public class SimpleRagService {

    private final EmbeddingClient embeddingClient;
    private final ResourceLoader resourceLoader;
    private VectorStore vectorStore;

    @PostConstruct
    public void init() {
        // 初始化内存向量存储
        this.vectorStore = new InMemoryVectorStore(embeddingClient);
        // 加载本地文档并存入向量库(示例)
        loadDocuments();
    }

    private void loadDocuments() {
        try {
            // 假设在 resources/documents 下有一个知识文件
            Resource resource = resourceLoader.getResource("classpath:documents/company_faq.txt");
            TextReader textReader = new TextReader(resource);
            textReader.getCustomMetadata().put("source", "company_faq.txt");

            // 读取文档
            List<Document> documents = textReader.get();

            // 文本分割器:将长文档切分成适合嵌入的小块
            TokenTextSplitter textSplitter = new TokenTextSplitter();
            List<Document> splitDocuments = textSplitter.apply(documents);

            // 将文档块添加到向量存储(会自动调用EmbeddingClient生成向量)
            vectorStore.add(splitDocuments);
            log.info("成功加载并向量化了 {} 个文档块。", splitDocuments.size());
        } catch (Exception e) {
            log.error("加载文档失败", e);
        }
    }

    /**
     * 基于向量检索的问答
     * @param question 用户问题
     * @return 结合检索内容的回答
     */
    public String ragChat(String question) {
        // 1. 检索:从向量库中查找与问题最相关的文档片段
        List<Document> similarDocuments = vectorStore.similaritySearch(question);
        log.info("检索到 {} 个相关文档片段。", similarDocuments.size());

        // 2. 构建增强后的Prompt
        StringBuilder context = new StringBuilder();
        for (Document doc : similarDocuments) {
            context.append(doc.getContent()).append("\n---\n");
        }

        String enhancedPrompt = String.format("""
                请基于以下上下文信息回答用户的问题。如果上下文信息不足以回答问题,请根据你的知识回答,并说明信息不足。
                
                上下文信息:
                %s
                
                用户问题:%s
                
                回答:
                """, context.toString(), question);

        // 3. 调用ChatClient(这里需要注入ChatClient,为了示例清晰,假设已注入)
        // ChatClient chatClient = ... 
        // return chatClient.prompt().user(enhancedPrompt).call().content();
        // 此处为示例,实际需要注入ChatClient
        return "这是一个RAG回答示例,实际需要结合检索到的上下文和模型调用。检索到的上下文片段数:" + similarDocuments.size();
    }
}

这个示例展示了RAG的基本流程:文档加载->文本分割->向量化存储->相似性检索->构建增强Prompt->调用LLM。在生产环境中,你需要将 InMemoryVectorStore 替换为 PgVectorStore (PostgreSQL)、 RedisVectorStore 等持久化方案。

5. 常见问题与排查思路

在集成Spring AI Alibaba过程中,你可能会遇到以下问题。

问题现象 可能原因 排查步骤与解决方案
启动报错: Failed to configure a DataSource 引入了数据库相关的starter(如JPA),但未配置数据源。 1. 检查 pom.xml ,如果不需要数据库,排除相关依赖。
2. 或者在 application.yml 中配置正确的数据库连接信息。
调用API返回 401 Unauthorized API Key配置错误或失效;Endpoint地址错误。 1. 检查 application.yml 中的 api-key base-url ,确保无误。
2. 登录阿里云百炼控制台,确认API Key状态是否正常、是否有余额或调用额度。
3. 确认 base-url 的路径是否正确,特别是 /compatible-mode/v1 部分。
调用API返回 404 Not Found Model not found 配置的模型名称不正确,或该模型在你所在区域未开通。 1. 检查 spring.ai.alibaba.bailian.chat.options.model 的值。
2. 前往百炼控制台“模型广场”或“模型部署”页面,查看你可用的模型列表,并使用正确的模型标识符。
应用启动正常,但 ChatClient 注入失败 Spring AI Alibaba Starter未正确引入或版本冲突;配置缺失。 1. 检查 pom.xml spring-ai-alibaba-bailian-spring-boot-starter 依赖是否存在且版本与BOM一致。
2. 检查 application.yml 中是否有 spring.ai.alibaba.bailian 配置节。
3. 查看启动日志,是否有关于 ChatClient EmbeddingClient Bean创建失败的警告。
流式响应不工作,一次性返回全部内容 客户端未正确支持SSE;Controller produces媒体类型设置错误。 1. 确保Controller方法返回 Flux<String> ,并且注解为 @GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
2. 使用正确的客户端(如 curl -N ,或前端使用 EventSource )进行测试。
3. 检查模型本身是否支持流式输出。
响应速度慢 网络延迟;模型本身生成速度;首次冷启动。 1. 检查网络连接。
2. 尝试使用响应更快的模型(如 qwen-turbo )。
3. 对于生产环境,考虑使用连接池、异步调用、缓存常见回答等优化策略。

6. 生产环境最佳实践与工程建议

将Spring AI Alibaba应用到生产环境,需要考虑更多工程化因素。

6.1 配置管理与安全

  • 密钥分离 :绝对不要将API Key硬编码在代码或配置文件中。必须使用环境变量、JVM参数或专业的密钥管理服务(如阿里云KMS、HashiCorp Vault)来注入。
    spring:
      ai:
        alibaba:
          bailian:
            api-key: ${ALIBABA_BAILIAN_API_KEY}
    
  • 多环境配置 :使用Spring Profiles为开发、测试、生产环境配置不同的模型、参数和端点(如果需要)。例如,开发环境使用较小、较快的模型,生产环境使用更强大、更稳定的模型。
  • 配置中心 :在微服务架构中,将AI相关配置(如模型名称、temperature、max-tokens)统一管理在Nacos、Apollo等配置中心,实现动态刷新和统一治理。

6.2 性能与稳定性

  • 超时与重试 :在 application.yml 中配置合理的超时时间和重试策略。Spring AI的HTTP客户端通常基于RestTemplate或WebClient,可以配置连接超时、读取超时。
    spring:
      ai:
        alibaba:
          bailian:
            client:
              connect-timeout: 10s
              read-timeout: 30s # LLM生成可能需要较长时间
    
  • 熔断与降级 :使用Resilience4j或Sentinel为AI服务调用添加熔断器。当AI服务不稳定或超时时,快速失败并返回预设的降级内容(如“服务繁忙,请稍后再试”或缓存的历史答案),避免拖垮整个应用。
  • 异步与非阻塞 :对于耗时较长的AI调用,务必使用异步处理(如 @Async CompletableFuture )或响应式编程(WebFlux + Mono / Flux ),避免阻塞Web容器线程,影响应用整体吞吐量。

6.3 可观测性与监控

  • 日志记录 :详细记录AI调用的请求和响应(注意脱敏,不要记录完整的Prompt和包含敏感信息的Response)。记录耗时、token使用量(如果API提供)、模型名称等信息,便于问题排查和成本分析。
  • Actuator与Metrics :Spring AI Actuator端点( /actuator/ai )提供了模型调用次数、耗时、错误率等指标。确保这些指标被集成到你的监控系统(如Prometheus + Grafana)中。
  • 链路追踪 :在微服务调用链中,将AI服务调用也作为一个Span加入分布式追踪(如SkyWalking, Jaeger),便于分析端到端延迟。

6.4 提示词工程与内容安全

  • 系统指令标准化 :为不同的业务场景(客服、代码生成、内容创作)设计标准化的系统指令模板,并将其作为配置或数据库条目管理,而不是硬编码在代码中。
  • 用户输入校验与过滤 :对用户输入的Prompt进行严格的校验、过滤和长度限制,防止注入攻击(Prompt Injection)和资源滥用。
  • 输出内容审核 :对于面向公众的应用,必须对模型的输出内容进行二次审核。可以结合阿里云的内容安全API或自建规则引擎,过滤不当、偏见或有害信息。
  • 上下文管理 :对于多轮对话,需要设计合理的上下文管理策略。是保存全部历史?还是只保存最近N轮?上下文长度会影响token消耗和模型性能。Spring AI提供了 ChatMemory 相关组件来辅助管理。

6.5 成本控制

  • 监控Token消耗 :密切关注API调用返回的token使用情况(输入+输出)。阿里云百炼等平台通常按token计费。建立成本预警机制。
  • 缓存策略 :对于常见、重复性高且答案相对固定的问题(如产品FAQ),可以将AI的回答结果缓存起来(使用Redis等),直接返回缓存结果,避免重复调用产生费用。
  • 模型选型 :根据业务场景的精度和响应速度要求,选择合适的模型。非关键场景或简单任务,可以使用成本更低的轻量模型(如 qwen-turbo )。

从环境搭建、核心概念理解,到完成第一个AI对话接口,再到探索流式响应和RAG进阶功能,我们走完了Spring AI Alibaba入门的核心路径。关键在于理解Spring AI的抽象层设计,它让我们能用一套统一的代码应对不同的AI服务商。

在实际项目中,建议先从一两个核心场景(如智能客服问答、代码注释生成)切入,将本文的示例代码跑通并集成到你的Spring Boot应用中。然后,再逐步深入考虑生产级的需求:如何管理配置密钥、如何设计提示词模板、如何实现异步调用和熔断降级、如何监控成本和性能。

Spring AI生态仍在快速发展,除了聊天和嵌入,其还在扩展函数调用(Function Calling)、多模态(图片、音频)等能力。保持对官方文档和社区动态的关注,将能让你更好地利用这个强大的框架,在Java世界中高效地构建智能应用。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐