Spring Alibaba AI 实战指南

Spring Alibaba AI 实战指南:构建企业级智能应用

摘要

Spring Alibaba AI 是阿里巴巴开源的 Spring AI 实现,为开发者提供了统一的 API 来集成各种大语言模型(LLM)服务。本文将深入探讨 Spring Alibaba AI 的核心特性、架构设计和实战应用,帮助开发者快速构建企业级智能应用。

目录

  1. Spring Alibaba AI 简介
  2. 核心架构与设计理念
  3. 快速开始
  4. 核心功能详解
  5. 生产环境最佳实践
  6. 与开源框架集成
  7. 常见问题与解决方案
  8. 总结与展望

1. Spring Alibaba AI 简介

1.1 什么是 Spring Alibaba AI

Spring Alibaba AI 是基于 Spring AI 框架的阿里云通义千问模型实现,提供了简洁、统一的 API 接口,让开发者能够轻松地将 AI 能力集成到 Spring Boot 应用中。

核心优势:

  • 统一的编程模型,降低学习成本
  • 开箱即用的 Spring Boot Starter
  • 支持流式响应和函数调用
  • 完善的错误处理和重试机制
  • 与 Spring 生态无缝集成

1.2 应用场景

复制代码
┌─────────────────────────────────────────────────────────┐
│              Spring Alibaba AI 应用场景                   │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐ │
│  │  智能客服    │  │  内容生成    │  │  代码助手    │ │
│  │              │  │              │  │              │ │
│  │ • 问答系统   │  │ • 文章写作   │  │ • 代码生成   │ │
│  │ • 意图识别   │  │ • 文案优化   │  │ • Bug修复    │ │
│  │ • 多轮对话   │  │ • 翻译服务   │  │ • 代码审查   │ │
│  └──────────────┘  └──────────────┘  └──────────────┘ │
│                                                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐ │
│  │  数据分析    │  │  知识库问答  │  │  文档理解    │ │
│  │              │  │              │  │              │ │
│  │ • 报表生成   │  │ • RAG应用    │  │ • 文档摘要   │ │
│  │ • 趋势预测   │  │ • 企业知识库 │  │ • 信息提取   │ │
│  │ • 异常检测   │  │ • 智能搜索   │  │ • 结构化输出 │ │
│  └──────────────┘  └──────────────┘  └──────────────┘ │
│                                                         │
└─────────────────────────────────────────────────────────┘

2. 核心架构与设计理念

2.1 整体架构

java 复制代码
┌────────────────────────────────────────────────────────────┐
│                    Spring Boot Application                  │
├────────────────────────────────────────────────────────────┤
│                                                            │
│  ┌──────────────────────────────────────────────────────┐ │
│  │              Application Layer (Controller)          │ │
│  └──────────────┬───────────────────────────────────────┘ │
│                 │                                          │
│  ┌──────────────▼───────────────────────────────────────┐ │
│  │         Service Layer (Business Logic)              │ │
│  └──────────────┬───────────────────────────────────────┘ │
│                 │                                          │
│  ┌──────────────▼───────────────────────────────────────┐ │
│  │            Spring AI Abstraction Layer              │ │
│  │  ┌────────────┐  ┌────────────┐  ┌────────────┐    │ │
│  │  │ ChatClient │  │   Prompt   │  │  Function  │    │ │
│  │  │            │  │  Template  │  │  Calling   │    │ │
│  │  └────────────┘  └────────────┘  └────────────┘    │ │
│  └──────────────┬───────────────────────────────────────┘ │
│                 │                                          │
│  ┌──────────────▼───────────────────────────────────────┐ │
│  │        Spring Alibaba AI Implementation             │ │
│  │  ┌────────────┐  ┌────────────┐  ┌────────────┐    │ │
│  │  │  ChatModel │  │ Embedding  │  │   Image    │    │ │
│  │  │            │  │   Model    │  │   Model    │    │ │
│  │  └────────────┘  └────────────┘  └────────────┘    │ │
│  └──────────────┬───────────────────────────────────────┘ │
│                 │                                          │
│  ┌──────────────▼───────────────────────────────────────┐ │
│  │          Alibaba Cloud Tongyi API                   │ │
│  └──────────────────────────────────────────────────────┘ │
│                                                            │
└────────────────────────────────────────────────────────────┘

2.2 核心组件

ChatClient: 提供流畅的 API 接口用于构建对话请求

ChatModel: 对话模型的抽象接口

Prompt: 提示词管理和模板化

StreamingChatModel: 支持流式响应的模型接口

FunctionCallback: 函数调用能力,让 AI 能够调用外部工具


3. 快速开始

3.1 环境准备

前置条件:

  • JDK 17+
  • Spring Boot 3.0+
  • Maven 3.6+ 或 Gradle 7.5+
  • 阿里云通义千问 API Key

3.2 添加依赖

Maven 配置:

xml 复制代码
<dependencies>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Alibaba AI Starter -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-ai</artifactId>
        <version>2023.0.1.0</version>
    </dependency>

    <!-- Spring Boot Starter Test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2023.0.1.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

3.3 配置文件

application.yml:

yaml 复制代码
spring:
  application:
    name: spring-alibaba-ai-demo

  cloud:
    ai:
      tongyi:
        api-key: ${TONGYI_API_KEY:your-api-key-here}
        chat:
          options:
            model: qwen-turbo
            temperature: 0.7
            max-tokens: 2000
            top-p: 0.9

# 日志配置
logging:
  level:
    com.alibaba.cloud.ai: DEBUG
    org.springframework.ai: DEBUG

3.4 第一个示例

简单的对话接口:

java 复制代码
package com.example.ai.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.*;

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

    private final ChatClient chatClient;

    public ChatController(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    @PostMapping("/simple")
    public String simpleChat(@RequestBody String message) {
        return chatClient.prompt()
                .user(message)
                .call()
                .content();
    }
}

启动类:

java 复制代码
package com.example.ai;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringAlibabaAiApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringAlibabaAiApplication.class, args);
    }
}

测试请求:

bash 复制代码
curl -X POST http://localhost:8080/api/chat/simple \
  -H "Content-Type: application/json" \
  -d "介绍一下Spring Boot的核心特性"

4. 核心功能详解

4.1 基础对话功能

4.1.1 同步对话
java 复制代码
package com.example.ai.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ChatService {

    private final ChatClient chatClient;
    private final ChatModel chatModel;

    public ChatService(ChatClient.Builder chatClientBuilder, ChatModel chatModel) {
        this.chatClient = chatClientBuilder.build();
        this.chatModel = chatModel;
    }

    /**
     * 基础对话 - 使用 ChatClient
     */
    public String chat(String userMessage) {
        return chatClient.prompt()
                .user(userMessage)
                .call()
                .content();
    }

    /**
     * 带系统提示的对话
     */
    public String chatWithSystem(String systemPrompt, String userMessage) {
        return chatClient.prompt()
                .system(systemPrompt)
                .user(userMessage)
                .call()
                .content();
    }

    /**
     * 使用 ChatModel 进行更底层的控制
     */
    public String chatWithModel(String userMessage) {
        Message message = new UserMessage(userMessage);
        Prompt prompt = new Prompt(List.of(message));
        return chatModel.call(prompt).getResult().getOutput().getContent();
    }

    /**
     * 多轮对话
     */
    public String multiTurnChat(List<Message> conversationHistory, String newMessage) {
        conversationHistory.add(new UserMessage(newMessage));
        Prompt prompt = new Prompt(conversationHistory);
        return chatModel.call(prompt).getResult().getOutput().getContent();
    }
}
4.1.2 流式响应
java 复制代码
package com.example.ai.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/api/stream")
public class StreamChatController {

    private final ChatClient chatClient;

    public StreamChatController(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    /**
     * SSE 流式响应
     */
    @GetMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamChat(@RequestParam String message) {
        return chatClient.prompt()
                .user(message)
                .stream()
                .content();
    }

    /**
     * 带系统提示的流式响应
     */
    @PostMapping(value = "/chat-with-context", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamChatWithContext(
            @RequestParam String systemPrompt,
            @RequestParam String userMessage) {
        return chatClient.prompt()
                .system(systemPrompt)
                .user(userMessage)
                .stream()
                .content();
    }
}

前端接收 SSE 示例(JavaScript):

javascript 复制代码
const eventSource = new EventSource('/api/stream/chat?message=讲一个故事');

eventSource.onmessage = function(event) {
    console.log('Received:', event.data);
    document.getElementById('output').textContent += event.data;
};

eventSource.onerror = function(error) {
    console.error('Error:', error);
    eventSource.close();
};

4.2 提示词工程

4.2.1 提示词模板
java 复制代码
package com.example.ai.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.stereotype.Service;

import java.util.Map;

@Service
public class PromptService {

    private final ChatClient chatClient;

    public PromptService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    /**
     * 使用提示词模板生成代码审查报告
     */
    public String reviewCode(String code, String language) {
        String template = """
                你是一位资深的代码审查专家。请对以下 {language} 代码进行详细审查:

                代码:
                ```{language}
                {code}
                ```

                请从以下维度进行审查:
                1. 代码质量和可读性
                2. 潜在的 Bug 和安全漏洞
                3. 性能优化建议
                4. 最佳实践和设计模式

                请以 Markdown 格式输出审查报告。
                """;

        PromptTemplate promptTemplate = new PromptTemplate(template);
        Map<String, Object> params = Map.of(
                "code", code,
                "language", language
        );

        return chatClient.prompt()
                .user(u -> u.text(promptTemplate.render(params)))
                .call()
                .content();
    }

    /**
     * 文档生成模板
     */
    public String generateDocumentation(String className, String methodSignature, String methodBody) {
        String template = """
                请为以下 Java 方法生成详细的 JavaDoc 文档:

                类名: {className}
                方法签名: {methodSignature}
                方法体:
                ```java
                {methodBody}
                ```

                要求:
                1. 包含方法描述
                2. 详细说明所有参数
                3. 说明返回值
                4. 列出可能抛出的异常
                5. 添加使用示例

                请使用标准的 JavaDoc 格式。
                """;

        PromptTemplate promptTemplate = new PromptTemplate(template);
        Map<String, Object> params = Map.of(
                "className", className,
                "methodSignature", methodSignature,
                "methodBody", methodBody
        );

        return chatClient.prompt()
                .user(u -> u.text(promptTemplate.render(params)))
                .call()
                .content();
    }

    /**
     * SQL 查询生成
     */
    public String generateSqlQuery(String tableSchema, String requirement) {
        String template = """
                根据以下数据库表结构和需求,生成优化的 SQL 查询:

                表结构:
                {tableSchema}

                查询需求:
                {requirement}

                要求:
                1. 生成高效的 SQL 查询语句
                2. 包含必要的索引建议
                3. 添加查询解释和注释
                4. 考虑性能优化
                """;

        PromptTemplate promptTemplate = new PromptTemplate(template);
        Map<String, Object> params = Map.of(
                "tableSchema", tableSchema,
                "requirement", requirement
        );

        return chatClient.prompt()
                .user(u -> u.text(promptTemplate.render(params)))
                .call()
                .content();
    }
}

4.3 函数调用(Function Calling)

函数调用是 Spring Alibaba AI 的强大特性,允许 AI 模型调用外部工具和服务。

4.3.1 定义函数
java 复制代码
package com.example.ai.function;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;

import java.util.function.Function;

/**
 * 天气查询函数
 */
public class WeatherFunction implements Function<WeatherFunction.Request, WeatherFunction.Response> {

    public record Request(
            @JsonProperty(required = true, value = "location")
            @JsonPropertyDescription("城市名称,例如:北京、上海")
            String location,

            @JsonProperty(required = false, value = "unit")
            @JsonPropertyDescription("温度单位:celsius(摄氏度) 或 fahrenheit(华氏度)")
            String unit
    ) {}

    public record Response(
            String location,
            double temperature,
            String unit,
            String condition,
            int humidity,
            String forecast
    ) {}

    @Override
    public Response apply(Request request) {
        // 模拟调用天气 API
        // 实际生产环境中,这里应该调用真实的天气服务
        String location = request.location();
        String unit = request.unit() != null ? request.unit() : "celsius";

        // 模拟数据
        double temperature = 22.5;
        String condition = "晴天";
        int humidity = 65;
        String forecast = "未来三天多云转晴";

        return new Response(location, temperature, unit, condition, humidity, forecast);
    }
}
4.3.2 注册和使用函数
java 复制代码
package com.example.ai.config;

import com.example.ai.function.WeatherFunction;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;

import java.util.function.Function;

@Configuration
public class FunctionConfig {

    @Bean
    @Description("获取指定城市的天气信息")
    public Function<WeatherFunction.Request, WeatherFunction.Response> weatherFunction() {
        return new WeatherFunction();
    }
}
java 复制代码
package com.example.ai.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.stereotype.Service;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;

@Service
public class FunctionCallingService {

    private final ChatClient chatClient;

    public FunctionCallingService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder
                .defaultFunctions("weatherFunction")  // 注册默认函数
                .build();
    }

    /**
     * 使用函数调用回答问题
     */
    public String chatWithFunction(String message) {
        return chatClient.prompt()
                .user(message)
                .call()
                .content();
    }

    /**
     * 带会话记忆的函数调用
     */
    public String chatWithFunctionAndMemory(String conversationId, String message) {
        return chatClient.prompt()
                .user(message)
                .advisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory()))
                .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, conversationId))
                .call()
                .content();
    }
}
4.3.3 复杂函数示例 - 数据库查询
java 复制代码
package com.example.ai.function;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * 数据库查询函数
 */
@Component
public class DatabaseQueryFunction implements Function<DatabaseQueryFunction.Request, DatabaseQueryFunction.Response> {

    private final JdbcTemplate jdbcTemplate;

    public DatabaseQueryFunction(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public record Request(
            @JsonProperty(required = true, value = "query")
            @JsonPropertyDescription("自然语言查询需求")
            String query,

            @JsonProperty(required = false, value = "limit")
            @JsonPropertyDescription("返回结果数量限制")
            Integer limit
    ) {}

    public record Response(
            String sql,
            List<Map<String, Object>> results,
            int rowCount,
            String message
    ) {}

    @Override
    public Response apply(Request request) {
        try {
            // 实际应用中,这里应该将自然语言转换为 SQL
            // 这里简化处理,假设已经有了 SQL
            String sql = convertToSql(request.query());

            int limit = request.limit() != null ? request.limit() : 10;
            sql = sql + " LIMIT " + limit;

            List<Map<String, Object>> results = jdbcTemplate.queryForList(sql);

            return new Response(
                    sql,
                    results,
                    results.size(),
                    "查询成功"
            );
        } catch (Exception e) {
            return new Response(
                    "",
                    List.of(),
                    0,
                    "查询失败: " + e.getMessage()
            );
        }
    }

    private String convertToSql(String naturalLanguageQuery) {
        // 简化示例:实际应该使用 AI 来转换
        // 这里仅作演示
        return "SELECT * FROM users WHERE 1=1";
    }
}

4.4 RAG (检索增强生成)

RAG 是构建企业级知识库问答系统的核心技术。

4.4.1 文档向量化
java 复制代码
package com.example.ai.service;

import org.springframework.ai.document.Document;
import org.springframework.ai.reader.TextReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class DocumentService {

    private final VectorStore vectorStore;
    private final TokenTextSplitter textSplitter;

    public DocumentService(VectorStore vectorStore) {
        this.vectorStore = vectorStore;
        // 配置文本分割器:每个块 500 个 token,重叠 100 个 token
        this.textSplitter = new TokenTextSplitter(500, 100);
    }

    /**
     * 将文档添加到向量数据库
     */
    public void addDocument(Resource resource) {
        // 读取文档
        TextReader textReader = new TextReader(resource);
        List<Document> documents = textReader.get();

        // 分割文档
        List<Document> chunks = textSplitter.apply(documents);

        // 存储到向量数据库
        vectorStore.add(chunks);
    }

    /**
     * 批量添加文档
     */
    public void addDocuments(List<Resource> resources) {
        resources.forEach(this::addDocument);
    }

    /**
     * 搜索相关文档
     */
    public List<Document> searchSimilarDocuments(String query, int topK) {
        return vectorStore.similaritySearch(query, topK);
    }
}
4.4.2 RAG 问答服务
java 复制代码
package com.example.ai.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;

@Service
public class RagService {

    private final ChatClient chatClient;
    private final VectorStore vectorStore;

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

    /**
     * 基于知识库的问答
     */
    public String askQuestion(String question) {
        return chatClient.prompt()
                .user(question)
                .advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
                .call()
                .content();
    }

    /**
     * 自定义检索策略的问答
     */
    public String askQuestionWithCustomSearch(String question, int topK, double similarityThreshold) {
        SearchRequest searchRequest = SearchRequest.defaults()
                .withTopK(topK)
                .withSimilarityThreshold(similarityThreshold);

        return chatClient.prompt()
                .user(question)
                .advisors(new QuestionAnswerAdvisor(vectorStore, searchRequest))
                .call()
                .content();
    }

    /**
     * 带引用来源的问答
     */
    public String askQuestionWithSources(String question) {
        String systemPrompt = """
                你是一个专业的知识库助手。在回答问题时:
                1. 基于提供的上下文信息准确回答
                2. 如果信息不足,明确说明
                3. 在回答末尾列出引用的文档来源
                """;

        return chatClient.prompt()
                .system(systemPrompt)
                .user(question)
                .advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
                .call()
                .content();
    }
}

5. 生产环境最佳实践

5.1 错误处理与重试

java 复制代码
package com.example.ai.service;

import io.github.resilience4j.retry.Retry;
import io.github.resilience4j.retry.RetryConfig;
import io.github.resilience4j.retry.RetryRegistry;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.retry.NonTransientAiException;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.function.Supplier;

@Service
public class ResilientChatService {

    private final ChatClient chatClient;
    private final Retry retry;

    public ResilientChatService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();

        // 配置重试策略
        RetryConfig config = RetryConfig.custom()
                .maxAttempts(3)
                .waitDuration(Duration.ofSeconds(2))
                .retryExceptions(Exception.class)
                .ignoreExceptions(NonTransientAiException.class)
                .build();

        RetryRegistry registry = RetryRegistry.of(config);
        this.retry = registry.retry("chatService");
    }

    /**
     * 带重试机制的对话
     */
    public String chatWithRetry(String message) {
        Supplier<String> supplier = Retry.decorateSupplier(retry, () ->
            chatClient.prompt()
                    .user(message)
                    .call()
                    .content()
        );

        return supplier.get();
    }
}

5.2 响应缓存

java 复制代码
package com.example.ai.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class CachedChatService {

    private final ChatClient chatClient;

    public CachedChatService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    /**
     * 缓存常见问题的回答
     */
    @Cacheable(value = "chatResponses", key = "#message")
    public String getCachedResponse(String message) {
        return chatClient.prompt()
                .user(message)
                .call()
                .content();
    }
}

缓存配置:

java 复制代码
package com.example.ai.config;

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager("chatResponses");
        cacheManager.setCaffeine(Caffeine.newBuilder()
                .maximumSize(1000)
                .expireAfterWrite(1, TimeUnit.HOURS)
                .recordStats());
        return cacheManager;
    }
}

5.3 限流与熔断

java 复制代码
package com.example.ai.service;

import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import io.github.resilience4j.ratelimiter.RateLimiter;
import io.github.resilience4j.ratelimiter.RateLimiterConfig;
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.function.Supplier;

@Service
public class ProtectedChatService {

    private final ChatClient chatClient;
    private final RateLimiter rateLimiter;
    private final CircuitBreaker circuitBreaker;

    public ProtectedChatService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();

        // 限流配置:每秒最多 10 个请求
        RateLimiterConfig rateLimiterConfig = RateLimiterConfig.custom()
                .limitForPeriod(10)
                .limitRefreshPeriod(Duration.ofSeconds(1))
                .timeoutDuration(Duration.ofSeconds(5))
                .build();

        RateLimiterRegistry rateLimiterRegistry = RateLimiterRegistry.of(rateLimiterConfig);
        this.rateLimiter = rateLimiterRegistry.rateLimiter("chatRateLimiter");

        // 熔断器配置
        CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
                .failureRateThreshold(50)
                .waitDurationInOpenState(Duration.ofMinutes(1))
                .slidingWindowSize(10)
                .build();

        CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(circuitBreakerConfig);
        this.circuitBreaker = circuitBreakerRegistry.circuitBreaker("chatCircuitBreaker");
    }

    /**
     * 带限流和熔断保护的对话
     */
    public String protectedChat(String message) {
        Supplier<String> supplier = () ->
            chatClient.prompt()
                    .user(message)
                    .call()
                    .content();

        // 应用限流
        supplier = RateLimiter.decorateSupplier(rateLimiter, supplier);

        // 应用熔断
        supplier = CircuitBreaker.decorateSupplier(circuitBreaker, supplier);

        return supplier.get();
    }
}

5.4 日志与监控

java 复制代码
package com.example.ai.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ChatLoggingAspect {

    private static final Logger logger = LoggerFactory.getLogger(ChatLoggingAspect.class);

    @Around("execution(* com.example.ai.service.*ChatService.*(..))")
    public Object logChatExecution(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();

        logger.info("开始执行 AI 对话方法: {}, 参数: {}", methodName, args);

        long startTime = System.currentTimeMillis();

        try {
            Object result = joinPoint.proceed();
            long duration = System.currentTimeMillis() - startTime;

            logger.info("AI 对话完成: {}, 耗时: {}ms", methodName, duration);

            return result;
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            logger.error("AI 对话失败: {}, 耗时: {}ms, 错误: {}",
                    methodName, duration, e.getMessage(), e);
            throw e;
        }
    }
}

6. 与开源框架集成

6.1 集成 LangChain4j

java 复制代码
package com.example.ai.integration;

import dev.langchain4j.chain.ConversationalChain;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;

/**
 * LangChain4j 集成示例
 * 注意:这是概念性示例,实际使用需要额外配置
 */
@Service
public class LangChain4jIntegrationService {

    private final ChatClient chatClient;

    public LangChain4jIntegrationService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    /**
     * 使用 Spring AI 作为底层模型
     */
    public String chatWithMemory(String conversationId, String message) {
        // 使用 Spring AI 的会话管理
        return chatClient.prompt()
                .user(message)
                .call()
                .content();
    }
}

6.2 集成 Spring Cloud

java 复制代码
package com.example.ai.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;

/**
 * Spring Cloud 集成配置
 */
@Configuration
public class CloudConfig {

    /**
     * 负载均衡的 WebClient
     */
    @Bean
    @LoadBalanced
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }
}
java 复制代码
package com.example.ai.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.stereotype.Service;

/**
 * 集成 Spring Cloud Circuit Breaker
 */
@Service
public class CloudAwareChatService {

    private final ChatClient chatClient;
    private final CircuitBreakerFactory circuitBreakerFactory;

    public CloudAwareChatService(
            ChatClient.Builder chatClientBuilder,
            CircuitBreakerFactory circuitBreakerFactory) {
        this.chatClient = chatClientBuilder.build();
        this.circuitBreakerFactory = circuitBreakerFactory;
    }

    public String chatWithCircuitBreaker(String message) {
        return circuitBreakerFactory.create("chatService").run(
                () -> chatClient.prompt()
                        .user(message)
                        .call()
                        .content(),
                throwable -> "服务暂时不可用,请稍后重试"
        );
    }
}

6.3 集成 Spring Security

java 复制代码
package com.example.ai.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(authz -> authz
                        .requestMatchers("/api/public/**").permitAll()
                        .requestMatchers("/api/chat/**").authenticated()
                        .anyRequest().authenticated()
                )
                .oauth2Login(oauth2 -> oauth2
                        .defaultSuccessUrl("/dashboard", true)
                );

        return http.build();
    }
}
java 复制代码
package com.example.ai.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

/**
 * 安全感知的聊天服务
 */
@Service
public class SecureChatService {

    private final ChatClient chatClient;

    public SecureChatService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    /**
     * 带用户上下文的对话
     */
    public String secureChat(String message) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String username = auth.getName();

        String systemPrompt = String.format(
                "你正在为用户 %s 提供服务。请记住用户身份,提供个性化的帮助。",
                username
        );

        return chatClient.prompt()
                .system(systemPrompt)
                .user(message)
                .call()
                .content();
    }
}

7. 常见问题与解决方案

7.1 API 限流问题

问题描述: 频繁调用 AI 接口导致触发限流。

解决方案:

java 复制代码
package com.example.ai.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

@Service
public class ThrottledChatService {

    private final ChatClient chatClient;
    private final Semaphore semaphore;
    private final ExecutorService executorService;

    public ThrottledChatService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
        // 限制并发请求数为 5
        this.semaphore = new Semaphore(5);
        this.executorService = Executors.newFixedThreadPool(10);
    }

    /**
     * 限流的异步对话
     */
    public CompletableFuture<String> asyncChatWithThrottle(String message) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                semaphore.acquire();
                return chatClient.prompt()
                        .user(message)
                        .call()
                        .content();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("请求被中断", e);
            } finally {
                semaphore.release();
            }
        }, executorService);
    }
}

7.2 超时处理

java 复制代码
package com.example.ai.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.concurrent.*;

@Service
public class TimeoutChatService {

    private final ChatClient chatClient;
    private final ExecutorService executorService;

    public TimeoutChatService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
        this.executorService = Executors.newCachedThreadPool();
    }

    /**
     * 带超时的对话
     */
    public String chatWithTimeout(String message, Duration timeout) {
        Future<String> future = executorService.submit(() ->
            chatClient.prompt()
                    .user(message)
                    .call()
                    .content()
        );

        try {
            return future.get(timeout.toMillis(), TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            future.cancel(true);
            throw new RuntimeException("请求超时", e);
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException("请求失败", e);
        }
    }
}

7.3 成本优化

java 复制代码
package com.example.ai.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.metadata.Usage;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
public class CostAwareChatService {

    private static final Logger logger = LoggerFactory.getLogger(CostAwareChatService.class);

    private final ChatClient chatClient;

    public CostAwareChatService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    /**
     * 跟踪 Token 使用情况
     */
    public String chatWithUsageTracking(String message) {
        ChatResponse response = chatClient.prompt()
                .user(message)
                .call()
                .chatResponse();

        // 获取使用情况
        Usage usage = response.getMetadata().getUsage();
        logger.info("Token 使用情况 - 提示词: {}, 完成: {}, 总计: {}",
                usage.getPromptTokens(),
                usage.getGenerationTokens(),
                usage.getTotalTokens());

        return response.getResult().getOutput().getContent();
    }

    /**
     * 使用更经济的模型
     */
    public String economicalChat(String message) {
        return chatClient.prompt()
                .user(message)
                .options(opts -> opts
                        .model("qwen-turbo")  // 使用更经济的模型
                        .maxTokens(1000))     // 限制输出长度
                .call()
                .content();
    }
}

8. 总结与展望

8.1 核心要点回顾

复制代码
┌─────────────────────────────────────────────────────────┐
│           Spring Alibaba AI 核心特性总结                  │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  1. 统一 API                                            │
│     └─ 简化 AI 集成,降低学习成本                        │
│                                                         │
│  2. 流式响应                                            │
│     └─ 提升用户体验,实时显示生成内容                     │
│                                                         │
│  3. 函数调用                                            │
│     └─ 扩展 AI 能力,集成外部工具和服务                   │
│                                                         │
│  4. RAG 支持                                            │
│     └─ 构建企业知识库,提供准确的领域回答                 │
│                                                         │
│  5. Spring 集成                                         │
│     └─ 无缝融入 Spring 生态系统                         │
│                                                         │
│  6. 生产就绪                                            │
│     └─ 错误处理、重试、限流、监控完善                     │
│                                                         │
└─────────────────────────────────────────────────────────┘

8.2 最佳实践建议

  1. 提示词工程:投入时间优化提示词,可以显著提升回答质量
  2. 错误处理:实现完善的重试和降级机制
  3. 性能优化:使用缓存、限流、异步处理
  4. 成本控制:监控 Token 使用,选择合适的模型
  5. 安全性:验证输入输出,防止注入攻击
  6. 可观测性:添加日志、指标、链路追踪

8.3 未来发展方向

多模态能力:

  • 图像理解与生成
  • 语音识别与合成
  • 视频分析

更强大的 Agent:

  • 自主规划和执行
  • 多 Agent 协作
  • 长期记忆管理

企业级特性:

  • 私有化部署支持
  • 细粒度权限控制
  • 审计和合规

8.4 参考资源

官方文档:


结语

Spring Alibaba AI 为 Java 开发者提供了强大而易用的 AI 集成能力。通过本文的介绍和示例,你应该能够:

  1. 理解 Spring Alibaba AI 的核心概念和架构
  2. 快速搭建基于 AI 的应用
  3. 掌握提示词工程、函数调用、RAG 等高级特性
  4. 应用生产环境的最佳实践
  5. 集成到现有的 Spring 应用中

AI 技术正在快速发展,Spring Alibaba AI 也在不断演进。建议持续关注官方文档和社区动态,探索更多可能性。

相关推荐
冰封剑心21 分钟前
MiniCPM-V-2_6 (4-bit 量化)使用
java·前端·数据库
mqiqe23 分钟前
【Spring AI MCP】四、MCP 服务端
java·人工智能·spring
l***749427 分钟前
springboot与springcloud对应版本
java·spring boot·spring cloud
稚辉君.MCA_P8_Java40 分钟前
Gemini永久会员 Java实现的暴力递归版本
java·数据结构·算法
许商1 小时前
【stm32】【printf】
java·前端·stm32
JIngJaneIL1 小时前
智慧物业|物业管理|基于SprinBoot+vue的智慧物业管理系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·论文·智慧物业管理系统
ANYOLY1 小时前
Redis 面试题库
java·redis·面试
该用户已不存在1 小时前
6款MCP工具,让AI真正懂业务
ai编程·mcp
懒惰蜗牛1 小时前
Day63 | Java IO之NIO三件套--选择器(下)
java·nio·选择器·selector·半包粘包·tcp缓冲区