关联知识库:Spring AI 深度解析:Java AI生态中的设计哲学与架构对比

Spring AI 深度解析:Java AI生态中的设计哲学与架构对比

前言:思维路线 (Thinking Roadmap)

本文档旨在为有4年以上Java开发经验、熟悉Spring生态的开发者,深入解析Spring AI框架的架构设计、设计哲学,以及它在Java AI生态中的独特定位。我们的探索路径如下:

  • 第一章:AI时代的到来 - 理解2023年以来生成式AI浪潮对企业级Java开发的冲击,以及Spring社区的响应
  • 第二章:Spring AI核心架构 - 深入剖析Spring AI的核心接口设计、多模型支持和企业级特性
  • 第三章:四大框架深度对比 - 横向对比LangChain、LlamaIndex、LangChain4j与Spring AI的架构差异与适用场景
  • 第四章:设计哲学剖析 - 揭示Spring AI如何延续Spring的"简化复杂性"理念,将模板模式应用于AI领域
  • 第五章:生态定位与选型 - 明确Spring AI在Java AI生态中的价值与选型建议
  • 第六章:实践示例 - 提供快速上手的代码示例

通过这条路径,我们将清晰地看到Spring AI不是简单的框架移植,而是基于Spring设计哲学的重新思考与原生设计


第一章:AI时代的到来与Spring的响应

时代背景:生成式AI的爆发

  • 2023年,ChatGPT现象:OpenAI的ChatGPT在2022年底发布后迅速席卷全球,大型语言模型(LLM)从研究领域走向大众应用
  • Python生态占据主导:LangChain、LlamaIndex等Python框架迅速崛起,成为AI应用开发的事实标准
  • 企业级Java应用的困境:数百万行的Spring应用如何快速集成AI能力?如何在保持企业级特性(安全、可观测、事务)的同时引入AI?

Spring AI的诞生

  • 项目启动:2023年,Spring团队正式启动Spring AI项目
  • 设计理念:不是简单移植Python框架,而是基于Spring的设计哲学重新设计
  • 核心使命
    1. 降低Java开发者的AI集成门槛 - 让熟悉Spring的开发者能够以最小学习成本使用AI
    2. 提供Spring式的开发体验 - 自动配置、依赖注入、统一抽象
    3. 实现企业级AI应用的快速落地 - 生产就绪、可观测、可扩展

项目定位

Spring AI不是一个独立的AI框架,而是Spring生态的自然延伸

  • Spring生态的AI扩展 - 与Spring Boot、Spring Data、Spring Security无缝集成
  • 面向企业级应用 - 优先考虑生产环境的稳定性、可维护性和安全性
  • 多模型、多供应商的统一抽象层 - 就像JdbcTemplate屏蔽不同数据库差异一样,Spring AI屏蔽不同AI模型的差异

️ 第二章:Spring AI核心架构与特性

核心接口抽象

Spring AI延续了Spring的"面向接口编程"传统,定义了一系列核心抽象接口:

1. ChatClient API - 对话模型的统一接口

// 流式的、可读性强的API设计(灵感来自RestClient/WebClient)
ChatClient chatClient = ChatClient.builder()
    .defaultSystem("你是一个专业的技术助手")
    .build();

String response = chatClient.prompt()
    .user("解释Spring的IoC容器")
    .call()
    .content();

设计亮点

  • Builder模式 - 链式调用,语义清晰
  • 统一返回类型 - ChatResponse封装了响应内容和元数据
  • 支持流式响应 - stream()方法返回Flux<ChatResponse>

2. EmbeddingModel - 向量化模型接口

EmbeddingModel embeddingModel; // 自动注入

List<Double> vector = embeddingModel.embed("Spring Framework");
// 支持批量向量化
List<List<Double>> vectors = embeddingModel.embed(List.of("text1", "text2"));

3. ImageModel - 图像生成模型接口

ImageModel imageModel;

ImageResponse response = imageModel.call(
    new ImagePrompt("一只在编程的猫")
);

4. PromptTemplate - 提示词模板管理

PromptTemplate template = new PromptTemplate("""
    你是一个{role},请帮我{task}。
    上下文:{context}
    """);

Prompt prompt = template.create(Map.of(
    "role", "架构师",
    "task", "设计微服务架构",
    "context", "电商系统"
));

设计亮点:像使用模板引擎一样管理Prompt,提升可维护性和复用性。


多模型支持矩阵

Spring AI支持业界主流的AI模型供应商,真正做到"Write Once, Run Anywhere":

供应商类型 支持的模型 Starter依赖
商业云服务 OpenAI (GPT-4, GPT-3.5) spring-ai-openai-spring-boot-starter
Azure OpenAI spring-ai-azure-openai-spring-boot-starter
Anthropic (Claude) spring-ai-anthropic-spring-boot-starter
Google VertexAI (Gemini) spring-ai-vertex-ai-gemini-spring-boot-starter
Amazon Bedrock spring-ai-bedrock-spring-boot-starter
本地/开源 Ollama (Llama, Mistral等) spring-ai-ollama-spring-boot-starter
Hugging Face spring-ai-huggingface-spring-boot-starter
中国厂商 阿里通义千问 (QianFan) spring-ai-qianfan-spring-boot-starter
智谱AI (ZhiPu) spring-ai-zhipuai-spring-boot-starter

切换成本:通常只需要修改Maven依赖和配置文件,代码无需改动!


️ RAG (检索增强生成) 能力

Spring AI为RAG提供了完整的ETL Pipeline支持:

1. 文档加载 (Document Loaders)

// 支持多种文档格式
DocumentReader pdfReader = new PagePdfDocumentReader(resource);
DocumentReader textReader = new TextReader(resource);
DocumentReader jsonReader = new JsonReader(resource);

List<Document> documents = pdfReader.get();

2. 文档切分 (Document Transformers)

TextSplitter splitter = new TokenTextSplitter();
List<Document> chunks = splitter.apply(documents);

3. 向量数据库集成

Spring AI支持20+种向量数据库,提供统一的VectorStore接口:

数据库类型 代表产品
专业向量库 Pinecone, Milvus, Qdrant, Weaviate, Chroma
传统数据库扩展 PostgreSQL/PGVector, MongoDB Atlas, Redis, Elasticsearch
图数据库 Neo4j
云服务 Azure AI Search, Azure Cosmos DB
@Bean
VectorStore vectorStore(EmbeddingModel embeddingModel, DataSource dataSource) {
    // 使用PostgreSQL的PGVector扩展
    return new PgVectorStore(dataSource, embeddingModel);
}

// 存储文档向量
vectorStore.add(documents);

// 相似度搜索
List<Document> results = vectorStore.similaritySearch(
    SearchRequest.query("Spring的事务管理").withTopK(5)
);

企业级特性

Spring AI不只是一个AI调用库,更是企业级应用开发平台

1. Spring Boot自动配置

# application.yml
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      chat:
        options:
          model: gpt-4
          temperature: 0.7

自动配置会:

  • 创建ChatClient.Builder Bean
  • 配置EmbeddingModel Bean
  • 设置默认参数和重试策略
  • 配置连接池和超时

2. 可观测性 (Observability)

基于Spring Boot Actuator和Micrometer,自动暴露AI相关指标:

management:
  endpoints:
    web:
      exposure:
        include: health,metrics,aimodels
  metrics:
    export:
      prometheus:
        enabled: true

自动收集的指标

  • AI调用次数、成功率、失败率
  • Token使用量统计
  • 响应时间分布
  • 成本估算(基于Token计费)

3. 工具调用 (Function Calling)

@Component
class WeatherService implements Function<WeatherRequest, WeatherResponse> {
    @Override
    public WeatherResponse apply(WeatherRequest request) {
        // 实际调用天气API
        return getWeather(request.city());
    }
}

// Spring AI自动将函数注册为可调用工具
ChatClient chatClient = ChatClient.builder()
    .defaultFunctions("weatherService") // 函数名即Bean名
    .build();

// AI会自动判断是否需要调用工具
String response = chatClient.prompt()
    .user("北京今天天气怎么样?")
    .call()
    .content();

4. 结构化输出 (Structured Output)

record BookRecommendation(
    String title,
    String author,
    String reason,
    int rating
) {}

BookRecommendation book = chatClient.prompt()
    .user("推荐一本Java并发编程的书")
    .call()
    .entity(BookRecommendation.class); // 自动解析为POJO

5. Advisors API - 可复用的AI模式

// 自动注入聊天历史
ChatClient chatClient = ChatClient.builder()
    .defaultAdvisors(
        new MessageChatMemoryAdvisor(chatMemory),
        new PromptChatMemoryAdvisor(chatMemory),
        new QuestionAnswerAdvisor(vectorStore) // RAG Advisor
    )
    .build();

Advisor模式:将常见的AI使用模式(如RAG、历史记忆、安全过滤)封装为可插拔的组件。


第三章:四大框架深度对比

对比框架概览

在AI应用开发领域,主要有四大框架值得关注:

框架 语言 诞生时间 核心定位
LangChain Python 2022 通用AI应用编排框架
LlamaIndex Python 2022 数据索引与检索专家
LangChain4j Java 2023 LangChain的Java实现
Spring AI Java 2023 Spring生态的AI原生框架

LangChain (Python)

定位与特点

定位:最全面的AI应用编排框架,概念体系最完整

核心概念

  • Chain(链) - 将多个步骤串联成工作流
  • Agent(智能体) - 能够自主决策和使用工具的AI实体
  • Memory(记忆) - 管理对话上下文和历史
  • Tools(工具) - 可被AI调用的外部能力

架构特点

from langchain import LLMChain, PromptTemplate
from langchain.agents import initialize_agent, Tool
from langchain.memory import ConversationBufferMemory

# 概念多、抽象层次高
agent = initialize_agent(
    tools=[search_tool, calculator_tool],
    llm=llm,
    agent="zero-shot-react-description",
    memory=ConversationBufferMemory(),
    verbose=True
)

优势

  • 生态最丰富 - 集成了500+外部工具和服务
  • 社区最活跃 - GitHub 80K+ stars,大量第三方扩展
  • 概念最完整 - Agent、Chain、Memory等成为行业术语标准

劣势

  • Python独占 - 无法直接用于Java生态
  • 复杂度高 - 概念多、抽象层次高,学习曲线陡峭
  • 性能开销 - 过度抽象导致运行时开销较大

适用场景

  • 复杂的AI工作流编排(多步骤推理、决策树)
  • 需要丰富的第三方集成
  • Python技术栈的团队

LlamaIndex (Python)

定位与特点

定位:专注于数据索引、检索和查询的专业框架

核心能力

  • 文档处理 - 支持PDF、Word、HTML、JSON等多种格式
  • 索引策略 - 向量索引、树索引、关键词索引、知识图谱索引
  • 查询引擎 - 19种查询引擎,支持多种检索模式
  • 后处理器 - 重排序、过滤、压缩等优化策略

架构特点

from llama_index import VectorStoreIndex, SimpleDirectoryReader

# 三行代码构建知识库
documents = SimpleDirectoryReader('data').load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()

response = query_engine.query("Spring的事务传播机制是什么?")

优势

  • 文档处理能力强 - 内置多种文档解析器和分割策略
  • 索引策略多样 - 支持多种索引类型,适应不同场景
  • 查询优化专业 - 提供完整的检索-后处理-生成链路

劣势

  • 功能相对单一 - 主要聚焦RAG,不涉及Agent等高级功能
  • 需组合使用 - 通常需要与LangChain等框架配合
  • Python限定 - 同样无法用于Java生态

适用场景

  • 企业知识库问答系统
  • 文档密集型应用(法律、医疗、金融)
  • 需要精细控制检索策略的场景

☕ LangChain4j (Java)

定位与特点

定位:LangChain的Java实现,功能对齐Python版

核心特点

  • 纯Java实现 - 不依赖Python环境
  • 概念对齐 - Chain、Agent、Memory等概念与LangChain一致
  • 可集成Spring - 但需要手动配置,非原生支持

架构特点

import dev.langchain4j.chain.ConversationalChain;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;

// 需要显式构建各个组件
ChatLanguageModel model = OpenAiChatModel.builder()
    .apiKey(System.getenv("OPENAI_API_KEY"))
    .modelName("gpt-4")
    .build();

ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);

ConversationalChain chain = ConversationalChain.builder()
    .chatLanguageModel(model)
    .chatMemory(chatMemory)
    .build();

String response = chain.execute("你好");

与Spring集成

// 需要手动创建Bean
@Configuration
public class LangChain4jConfig {
    @Bean
    public ChatLanguageModel chatModel(@Value("${openai.api-key}") String apiKey) {
        return OpenAiChatModel.builder()
            .apiKey(apiKey)
            .build();
    }
}

优势

  • 纯Java - 无需Python环境,适合Java团队
  • 功能完整 - Agent、RAG、工具调用等功能齐全
  • 可与Spring集成 - 虽然需要手动配置

劣势

  • 缺乏自动配置 - 没有Spring Boot Starter,需要大量样板代码
  • 非Spring原生 - 设计理念不同,无法享受Spring生态福利
  • 社区相对小 - 相比LangChain,社区规模和生态仍在成长期

适用场景

  • 需要LangChain能力但必须用Java的项目
  • 不使用Spring框架的Java应用
  • 需要精细控制AI调用流程的场景

Spring AI (Java)

定位与特点

定位:Spring生态的AI原生框架,为Spring开发者而生

设计理念

  • 不是移植,而是重新设计 - 基于Spring哲学,而非照搬Python框架
  • Spring优先 - 深度集成Spring Boot、Spring Data、Spring Security
  • 约定优于配置 - 自动配置、Starter依赖、默认参数

架构特点

// 1. 添加依赖
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>

// 2. 配置(极简)
spring.ai.openai.api-key=${OPENAI_API_KEY}

// 3. 使用(自动注入)
@RestController
class ChatController {
    private final ChatClient chatClient;
    
    ChatController(ChatClient.Builder builder) {
        this.chatClient = builder.build(); // 自动配置的Builder
    }
    
    @GetMapping("/chat")
    String chat(@RequestParam String message) {
        return chatClient.prompt().user(message).call().content();
    }
}

优势

  • 深度集成Spring Boot - 自动配置、健康检查、指标暴露
  • 统一抽象层 - 易于切换模型供应商,降低供应商锁定风险
  • 企业级特性 - 事务管理、安全集成、可观测性、测试支持
  • 学习成本低 - Spring开发者零门槛,API设计与RestClient/JdbcTemplate一脉相承
  • 生产就绪 - 内置重试、熔断、限流等企业级能力

劣势

  • ⚠️ 相对年轻 - 2023年起步,生态仍在快速建设中
  • ⚠️ 需要Spring环境 - 强依赖Spring Boot,不适合非Spring项目

适用场景

  • 现有Spring应用集成AI(最佳选择)
  • 企业级Java应用 - 需要生产级别的稳定性和可观测性
  • 快速原型开发 - 自动配置大幅降低初始化成本
  • 多云/多模型场景 - 统一抽象便于切换

四大框架对比总结表

对比维度 LangChain LlamaIndex LangChain4j Spring AI
语言生态 Python Python Java Java
学习曲线 陡峭(概念多) 中等 陡峭 平缓
Spring集成 ❌ 不支持 ❌ 不支持 ⚠️ 手动集成 ✅ 原生支持
自动配置 ✅ Spring Boot Starter
功能完整性 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐
企业级特性 ⭐⭐⭐ ⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐
可观测性 需自行集成 需自行集成 需自行集成 内置(Actuator)
事务支持 部分 ✅ 完整
社区成熟度 高(80K+ stars) 中(30K+ stars) 中(3K+ stars) 快速增长
供应商切换 需改代码 需改代码 需改代码 仅改配置
测试支持 基础 基础 基础 完善(Mock/Testcontainers)

选型决策树

是否必须使用Java?
├─ 否 → Python技术栈
│   ├─ 需要复杂工作流编排?
│   │   ├─ 是 → LangChain(功能最全)
│   │   └─ 否 → LlamaIndex(专注RAG)
│   └─ 
└─ 是 → Java技术栈
    ├─ 是否使用Spring框架?
    │   ├─ 是 → Spring AI(强烈推荐)
    │   │   理由:
    │   │   • 零学习成本(Spring开发者)
    │   │   • 自动配置,开箱即用
    │   │   • 企业级特性完整
    │   │   • 生态集成度最高
    │   │
    │   └─ 否 → LangChain4j
    │       理由:
    │       • 纯Java,无Spring依赖
    │       • 功能对齐LangChain
    │       • 社区相对活跃
    │
    └─ 特殊场景
        • 需要LangChain的Agent能力 → LangChain4j
        • 已有Spring应用快速AI化 → Spring AI
        • 多模型切换需求 → Spring AI

第四章:设计哲学深度剖析

"Spring式"的AI开发

Spring AI不是简单地提供AI调用能力,而是将Spring的设计哲学完整应用到AI领域:

1. 约定优于配置 (Convention over Configuration)

JPA/Hibernate的启发

// Hibernate时代:大量XML配置
<hibernate-mapping>
  <class name="User" table="users">
    <id name="id" column="user_id"/>
    ...
  </class>
</hibernate-mapping>

// Spring Data JPA时代:约定优于配置
@Entity
public class User {
    @Id
    private Long id;
}

Spring AI的应用

// 无需配置,添加Starter即可
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>

// 配置文件极简(约定了默认值)
spring.ai.openai.api-key=xxx
# 默认:gpt-3.5-turbo, temperature=0.7, max-tokens=800

2. 面向接口编程 (Program to Interface)

Spring的一贯传统

  • DataSource → 屏蔽MySQL/PostgreSQL/Oracle
  • CacheManager → 屏蔽Redis/Caffeine/Hazelcast
  • MessageConverter → 屏蔽JSON/XML/Protobuf

Spring AI的延续

  • ChatModel → 屏蔽OpenAI/Azure/Anthropic/Ollama
  • EmbeddingModel → 屏蔽不同的向量化模型
  • VectorStore → 屏蔽Pinecone/Qdrant/PGVector

可移植性的威力

@Service
public class AiService {
    private final ChatModel chatModel; // 接口注入,而非具体实现
    
    public String chat(String message) {
        return chatModel.call(message);
    }
}

// 切换供应商只需改配置
# 使用OpenAI
spring.ai.openai.api-key=xxx

# 切换到Ollama(本地模型)
spring.ai.ollama.base-url=http://localhost:11434
spring.ai.ollama.chat.model=llama2

无需修改一行代码!


3. 模板模式的运用 (Template Pattern)

Spring历史上的经典"Template"系列:

Template 屏蔽的复杂性 开发者只需关注
JdbcTemplate 连接管理、异常转换、资源释放 SQL逻辑
RestTemplate HTTP连接、序列化/反序列化、错误处理 请求参数和响应处理
TransactionTemplate 事务开启、提交、回滚 业务逻辑

ChatClient的设计

// 对比JdbcTemplate
String userName = jdbcTemplate.queryForObject(
    "SELECT name FROM users WHERE id = ?",
    String.class,
    userId
);

// ChatClient的相似性
String response = chatClient.prompt()
    .user("解释Spring的{concept}")
    .call()
    .content();

模板模式的本质

  • 封装不变的部分 - HTTP调用、JSON序列化、错误重试
  • 暴露可变的部分 - Prompt内容、参数设置
  • 提供优雅的API - 链式调用、语义清晰

4. 依赖注入的威力 (Dependency Injection)

传统AI调用方式(以OpenAI为例):

// 硬编码,难以测试和切换
public class ChatService {
    public String chat(String message) {
        OpenAI client = new OpenAI(System.getenv("OPENAI_API_KEY"));
        return client.chat(message); // 与OpenAI强耦合
    }
}

Spring AI方式

@Service
public class ChatService {
    private final ChatClient chatClient;
    
    // 依赖注入,易于测试和切换
    public ChatService(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }
    
    public String chat(String message) {
        return chatClient.prompt().user(message).call().content();
    }
}

// 测试时轻松Mock
@SpringBootTest
class ChatServiceTest {
    @MockBean
    ChatClient.Builder builder;
    
    @Test
    void testChat() {
        // Mock返回固定响应,无需真实调用AI
    }
}

从JdbcTemplate到ChatClient的类比

这是理解Spring AI设计哲学的核心类比

维度 JdbcTemplate RestTemplate ChatClient
解决的问题 简化数据库访问 简化HTTP调用 简化AI调用
屏蔽的复杂性 JDBC样板代码 HTTP连接管理 AI API差异
统一的抽象 SQL执行 RESTful请求 Prompt调用
异常处理 DataAccessException RestClientException AiException
支持多实现 MySQL, PostgreSQL, Oracle HTTP/1.1, HTTP/2 OpenAI, Azure, Ollama
配置方式 DataSource RestTemplateBuilder ChatClient.Builder

设计思想一脉相承

  • 简化复杂性 - 将繁琐的底层操作封装为简洁的API
  • 提供优雅抽象 - 屏蔽实现细节,暴露业务语义
  • 支持可扩展性 - 易于集成新的实现
  • 保持一致性 - API设计风格统一,降低学习成本

代码对比

// JdbcTemplate - 1999年设计
List<User> users = jdbcTemplate.query(
    "SELECT * FROM users WHERE age > ?",
    new Object[]{18},
    (rs, rowNum) -> new User(rs.getString("name"))
);

// RestTemplate - 2009年设计
User user = restTemplate.getForObject(
    "https://api.example.com/users/{id}",
    User.class,
    userId
);

// ChatClient - 2023年设计
BookRecommendation book = chatClient.prompt()
    .user("推荐一本Java并发编程的书")
    .call()
    .entity(BookRecommendation.class);

共同特征

  • ✅ 流式API,可读性强
  • ✅ 类型安全(泛型支持)
  • ✅ 异常转换(统一异常体系)
  • ✅ 资源管理(自动释放)

企业级优先 (Enterprise First)

Spring AI与其他框架最大的区别在于:从第一天起就面向企业级场景设计

1. 可观测性内置 (Built-in Observability)

其他框架:需要自行集成监控

// LangChain4j - 需要手动添加监控
long start = System.currentTimeMillis();
try {
    String response = model.chat(message);
    metrics.recordSuccess(System.currentTimeMillis() - start);
} catch (Exception e) {
    metrics.recordFailure();
    throw e;
}

Spring AI:开箱即用的可观测性

# 自动暴露AI相关指标
management:
  endpoints:
    web:
      exposure:
        include: metrics,health

自动收集的指标

  • spring.ai.chat.calls - 调用次数
  • spring.ai.chat.duration - 响应时间
  • spring.ai.chat.tokens - Token使用量
  • spring.ai.chat.errors - 错误次数

2. 安全性考量 (Security)

与Spring Security无缝集成

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) {
        http.authorizeHttpRequests(auth -> auth
            .requestMatchers("/ai/**").hasRole("AI_USER") // AI接口需要权限
            .anyRequest().authenticated()
        );
        return http.build();
    }
}

// 敏感数据过滤
@Component
class DataMaskingAdvisor implements RequestResponseAdvisor {
    @Override
    public AdvisedRequest adviseRequest(AdvisedRequest request) {
        // 自动脱敏用户输入中的敏感信息
        String masked = maskSensitiveData(request.userText());
        return request.updateUserText(masked);
    }
}

3. 事务管理 (Transaction Management)

AI调用与数据库事务的协同

@Service
public class OrderService {
    private final ChatClient chatClient;
    private final OrderRepository orderRepository;
    
    @Transactional
    public Order processOrder(OrderRequest request) {
        // 1. AI生成订单摘要
        String summary = chatClient.prompt()
            .user("总结订单:" + request)
            .call()
            .content();
        
        // 2. 保存订单(同一事务)
        Order order = new Order(request, summary);
        orderRepository.save(order);
        
        // 如果AI调用失败或保存失败,整个事务回滚
        return order;
    }
}

4. 测试友好 (Test-Friendly)

Mock支持

@SpringBootTest
class AiServiceTest {
    @MockBean
    ChatModel chatModel; // Mock AI模型
    
    @Test
    void testChatWithMock() {
        // 不调用真实AI,返回预设响应
        when(chatModel.call(any()))
            .thenReturn(new ChatResponse("Mocked response"));
        
        String response = aiService.chat("test");
        assertEquals("Mocked response", response);
    }
}

Testcontainers支持

@SpringBootTest
@Testcontainers
class VectorStoreTest {
    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>()
        .withInitScript("init-pgvector.sql");
    
    @Test
    void testVectorSearch() {
        // 使用真实的PostgreSQL + PGVector测试
    }
}

第五章:在Java AI生态中的定位

生态位分析

Python AI生态                Java AI生态
┌─────────────────────┐      ┌──────────────────────┐
│                     │      │                      │
│  LangChain          │ ≈    │  LangChain4j         │ (概念对齐)
│  - Agent编排        │      │  - Agent编排         │
│  - 工作流管理       │      │  - 工作流管理        │
│  - 生态最丰富       │      │  - 纯Java实现        │
│                     │      │                      │
│  LlamaIndex         │ ≈    │  Spring AI           │ (Spring优先)
│  - RAG专家          │      │  - 企业级AI平台      │
│  - 文档处理         │      │  - Spring生态集成    │
│  - 索引优化         │      │  - 自动配置          │
│                     │      │  - 生产就绪          │
└─────────────────────┘      └──────────────────────┘

        ↓ 互相借鉴                    ↓ 各自发展
        
    并非移植关系                 基于不同设计哲学

Spring AI的独特价值

1. 不是移植,而是重新设计

LangChain4j的方式

  • 目标:将LangChain的概念完整移植到Java
  • 结果:保留了LangChain的复杂性和学习曲线

Spring AI的方式

  • 目标:为Spring开发者提供自然的AI集成体验
  • 结果:基于Spring哲学重新设计,简化概念模型

对比示例 - 实现相同功能

// LangChain4j风格 - 概念多,配置繁琐
ChatLanguageModel model = OpenAiChatModel.builder()
    .apiKey(apiKey)
    .modelName("gpt-4")
    .temperature(0.7)
    .maxTokens(800)
    .build();

ChatMemory memory = MessageWindowChatMemory.withMaxMessages(10);

ConversationalChain chain = ConversationalChain.builder()
    .chatLanguageModel(model)
    .chatMemory(memory)
    .build();

String response = chain.execute("你好");

// Spring AI风格 - 简洁,符合Spring习惯
spring.ai.openai.api-key=${OPENAI_API_KEY}

@RestController
class ChatController {
    private final ChatClient chatClient;
    
    ChatController(ChatClient.Builder builder) {
        this.chatClient = builder
            .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory))
            .build();
    }
    
    @GetMapping("/chat")
    String chat(@RequestParam String message) {
        return chatClient.prompt().user(message).call().content();
    }
}

Spring AI简化的关键

  • 自动配置 - 减少90%的样板代码
  • 依赖注入 - 符合Spring开发者习惯
  • 统一抽象 - 降低概念复杂度

2. 面向企业级场景

对比维度

企业需求 LangChain LangChain4j Spring AI
生产就绪 需自行加固 需自行加固 ✅ 内置
可观测性 需集成APM 需自行实现 ✅ Actuator
安全集成 需自行实现 需自行实现 ✅ Spring Security
配置管理 代码配置 代码配置 ✅ Config Server
服务发现 ✅ Spring Cloud
熔断限流 需自行集成 需自行集成 ✅ Resilience4j
分布式追踪 需集成 需集成 ✅ Micrometer Tracing

企业场景示例

// Spring AI的企业级能力
@Configuration
public class AiConfig {
    @Bean
    ChatClient chatClient(ChatClient.Builder builder) {
        return builder
            .defaultSystem("你是企业AI助手")
            // 1. 安全过滤
            .defaultAdvisors(new SafetyFilterAdvisor())
            // 2. 成本控制
            .defaultAdvisors(new TokenLimitAdvisor(maxTokens))
            // 3. 审计日志
            .defaultAdvisors(new AuditLogAdvisor())
            // 4. 熔断保护
            .defaultAdvisors(new CircuitBreakerAdvisor())
            .build();
    }
}

// 自动暴露健康检查
GET /actuator/health/ai
{
  "status": "UP",
  "components": {
    "openai": {
      "status": "UP",
      "latency": "234ms"
    }
  }
}

3. 降低现有应用的迁移成本

场景:一个已有的Spring Boot电商系统,需要添加AI客服功能

使用LangChain4j

// 1. 添加依赖
<dependency>
  <groupId>dev.langchain4j</groupId>
  <artifactId>langchain4j-openai</artifactId>
</dependency>

// 2. 手动创建配置类
@Configuration
public class LangChain4jConfig {
    @Bean
    public ChatLanguageModel chatModel() {
        return OpenAiChatModel.builder()...build();
    }
    
    @Bean
    public ChatMemory chatMemory() {
        return MessageWindowChatMemory.withMaxMessages(10);
    }
    
    @Bean
    public ConversationalChain chain(ChatLanguageModel model, ChatMemory memory) {
        return ConversationalChain.builder()...build();
    }
}

// 3. 手动集成到现有服务
@Service
public class CustomerService {
    private final ConversationalChain chain;
    // 需要适配不同的编程模型
}

使用Spring AI

// 1. 添加依赖(仅此而已)
<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>

// 2. 配置文件
spring.ai.openai.api-key=${OPENAI_API_KEY}

// 3. 直接注入使用(零学习成本)
@Service
public class CustomerService {
    private final ChatClient chatClient;
    
    // 与现有Spring代码风格完全一致
    public CustomerService(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }
}

迁移成本对比

  • LangChain4j:需要学习新的API、手动配置、适配现有架构 → 2-3天
  • Spring AI:添加依赖、配置API Key、注入使用 → 30分钟

4. Java开发者的首选

为什么Spring开发者会自然选择Spring AI

  1. 零学习成本

    // 熟悉的Builder模式
    RestTemplate restTemplate = new RestTemplateBuilder()...build();
    ChatClient chatClient = new ChatClient.Builder()...build();
    
    // 熟悉的依赖注入
    @Autowired private DataSource dataSource;
    @Autowired private ChatClient chatClient;
    
  2. 统一的编程体验

    // 查数据库
    String name = jdbcTemplate.queryForObject("SELECT name...", String.class);
    
    // 调REST API
    User user = restTemplate.getForObject("/users/{id}", User.class, id);
    
    // 调AI模型(风格完全一致)
    String answer = chatClient.prompt().user("...").call().content();
    
  3. 一致的配置管理

    # 数据库配置
    spring.datasource.url=jdbc:mysql://localhost/db
    
    # Redis配置
    spring.redis.host=localhost
    
    # AI配置(风格一致)
    spring.ai.openai.api-key=xxx
    
  4. 统一的监控和运维

    # 同一套Actuator监控所有组件
    GET /actuator/health
    {
      "datasource": "UP",
      "redis": "UP",
      "ai": "UP"  // AI健康检查
    }
    

框架选型建议

决策矩阵

你的情况 推荐框架 理由
已有Spring应用,需要集成AI ✅ Spring AI • 零学习成本
• 自动配置
• 无缝集成
新Java项目,计划用Spring ✅ Spring AI • 未来扩展性好
• 企业级特性完整
Java项目,但不用Spring LangChain4j • 纯Java
• 功能完整
• 无框架依赖
需要复杂的Agent编排 LangChain4j 或 LangChain • Agent能力更成熟
• 生态工具更丰富
Python技术栈 LangChain • 社区最活跃
• 生态最完善
专注RAG和文档检索 LlamaIndex 或 Spring AI • LlamaIndex更专业
• Spring AI更易集成
需要多模型切换 ✅ Spring AI • 统一抽象
• 配置即切换
快速原型验证 ✅ Spring AI • 自动配置最快
• 代码量最少

真实场景案例

场景1:传统Spring应用AI化

需求:为已有的客服系统添加AI对话功能
技术栈:Spring Boot 3.2 + MySQL + Redis
选型:Spring AI ⭐⭐⭐⭐⭐

理由:
• 开发时间:半天(vs LangChain4j需要2-3天)
• 代码量:50行(vs LangChain4j需要200+行)
• 运维成本:复用现有监控体系

场景2:新Java AI项目,非Spring

需求:开发一个轻量级的AI CLI工具
技术栈:纯Java 17,无Web框架
选型:LangChain4j ⭐⭐⭐⭐

理由:
• 不需要Spring的重量级依赖
• LangChain4j功能完整
• 可直接打包为GraalVM原生镜像

场景3:复杂的AI工作流

需求:多步骤推理、自动规划、工具调用
技术栈:灵活选择
选型:LangChain (Python) ⭐⭐⭐⭐⭐

理由:
• Agent能力最成熟
• 工具生态最丰富(500+集成)
• 社区资源最多

第六章:实践示例

快速开始:最小化Chat应用

步骤1:创建Spring Boot项目

# 使用Spring Initializr
curl https://start.spring.io/starter.zip \
  -d dependencies=web,spring-ai-openai \
  -d bootVersion=3.2.0 \
  -d javaVersion=17 \
  -o spring-ai-demo.zip

unzip spring-ai-demo.zip
cd spring-ai-demo

步骤2:配置API Key

# src/main/resources/application.yml
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}  # 从环境变量读取
      chat:
        options:
          model: gpt-4
          temperature: 0.7

步骤3:编写Controller

package com.example.demo;

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

@RestController
@RequestMapping("/ai")
public class AiController {
    
    private final ChatClient chatClient;
    
    // 构造器注入(Spring AI自动配置的Builder)
    public AiController(ChatClient.Builder builder) {
        this.chatClient = builder
            .defaultSystem("你是一个专业的技术助手,擅长解释Java和Spring相关概念")
            .build();
    }
    
    @GetMapping("/chat")
    public String chat(@RequestParam String message) {
        return chatClient.prompt()
            .user(message)
            .call()
            .content();
    }
    
    @GetMapping("/stream")
    public reactor.core.publisher.Flux<String> streamChat(@RequestParam String message) {
        // 流式响应
        return chatClient.prompt()
            .user(message)
            .stream()
            .content();
    }
}

步骤4:启动测试

# 设置环境变量
export OPENAI_API_KEY=sk-your-api-key

# 启动应用
./mvnw spring-boot:run

# 测试
curl "http://localhost:8080/ai/chat?message=解释Spring的IoC容器"

返回示例

Spring的IoC(Inversion of Control,控制反转)容器是框架的核心...

进阶示例:RAG知识库问答

场景描述

构建一个基于企业文档的智能问答系统,能够:

  • 加载PDF/Word/Markdown文档
  • 自动向量化并存储到向量数据库
  • 基于用户问题检索相关文档
  • 结合检索内容生成回答

完整实现

1. 添加依赖

<dependencies>
    <!-- Spring AI OpenAI -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    </dependency>
    
    <!-- PGVector向量数据库 -->
    <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>
</dependencies>

2. 配置文件

spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      embedding:
        options:
          model: text-embedding-3-small
  
  datasource:
    url: jdbc:postgresql://localhost:5432/vectordb
    username: postgres
    password: postgres
    
  ai:
    vectorstore:
      pgvector:
        initialize-schema: true
        dimensions: 1536  # OpenAI embedding维度

3. 文档加载服务

@Service
public class DocumentService {
    
    private final VectorStore vectorStore;
    
    public DocumentService(VectorStore vectorStore) {
        this.vectorStore = vectorStore;
    }
    
    /**
     * 加载PDF文档并向量化存储
     */
    public void loadPdfDocument(Resource pdfResource) {
        // 1. 读取PDF
        PagePdfDocumentReader pdfReader = new PagePdfDocumentReader(
            pdfResource,
            PdfDocumentReaderConfig.builder()
                .withPageTopMargin(0)
                .withPageBottomMargin(0)
                .build()
        );
        List<Document> documents = pdfReader.get();
        
        // 2. 文档切分(可选,如果文档太大)
        TextSplitter splitter = new TokenTextSplitter();
        List<Document> chunks = splitter.apply(documents);
        
        // 3. 向量化并存储(自动调用EmbeddingModel)
        vectorStore.add(chunks);
        
        System.out.println("成功加载 " + chunks.size() + " 个文档块");
    }
    
    /**
     * 批量加载目录下所有文档
     */
    public void loadDirectory(Path directory) throws IOException {
        Files.walk(directory)
            .filter(path -> path.toString().endsWith(".pdf"))
            .forEach(path -> {
                try {
                    loadPdfDocument(new FileSystemResource(path.toFile()));
                } catch (Exception e) {
                    System.err.println("加载失败: " + path);
                }
            });
    }
}

4. RAG问答服务

@Service
public class RagService {
    
    private final ChatClient chatClient;
    private final VectorStore vectorStore;
    
    public RagService(ChatClient.Builder builder, VectorStore vectorStore) {
        this.vectorStore = vectorStore;
        this.chatClient = builder
            .defaultAdvisors(new QuestionAnswerAdvisor(vectorStore))  // RAG Advisor
            .build();
    }
    
    /**
     * 基于知识库的问答(手动RAG)
     */
    public String answerWithContext(String question) {
        // 1. 相似度搜索
        List<Document> relatedDocs = vectorStore.similaritySearch(
            SearchRequest.query(question).withTopK(3)
        );
        
        // 2. 构建上下文
        String context = relatedDocs.stream()
            .map(Document::getContent)
            .collect(Collectors.joining("\n\n"));
        
        // 3. 生成Prompt
        String prompt = """
            请基于以下知识库内容回答问题。如果知识库中没有相关信息,请明确说明。
            
            知识库内容:
            {context}
            
            用户问题:{question}
            
            回答:
            """;
        
        // 4. 调用AI生成回答
        return chatClient.prompt()
            .user(u -> u.text(prompt)
                .param("context", context)
                .param("question", question))
            .call()
            .content();
    }
    
    /**
     * 基于知识库的问答(使用Advisor自动RAG)
     */
    public String answerWithAdvisor(String question) {
        // QuestionAnswerAdvisor会自动:
        // 1. 检索相关文档
        // 2. 注入到Prompt
        // 3. 生成回答
        return chatClient.prompt()
            .user(question)
            .call()
            .content();
    }
}

5. REST API

@RestController
@RequestMapping("/rag")
public class RagController {
    
    private final DocumentService documentService;
    private final RagService ragService;
    
    public RagController(DocumentService documentService, RagService ragService) {
        this.documentService = documentService;
        this.ragService = ragService;
    }
    
    /**
     * 上传文档
     */
    @PostMapping("/documents")
    public String uploadDocument(@RequestParam("file") MultipartFile file) throws IOException {
        Resource resource = file.getResource();
        documentService.loadPdfDocument(resource);
        return "文档上传成功";
    }
    
    /**
     * 问答接口
     */
    @GetMapping("/ask")
    public Map<String, Object> ask(@RequestParam String question) {
        String answer = ragService.answerWithAdvisor(question);
        return Map.of(
            "question", question,
            "answer", answer,
            "timestamp", System.currentTimeMillis()
        );
    }
}

6. 测试使用

# 1. 启动PostgreSQL(带PGVector扩展)
docker run -d \
  -e POSTGRES_PASSWORD=postgres \
  -e POSTGRES_DB=vectordb \
  -p 5432:5432 \
  ankane/pgvector

# 2. 启动应用
export OPENAI_API_KEY=sk-xxx
./mvnw spring-boot:run

# 3. 上传文档
curl -X POST http://localhost:8080/rag/documents \
  -F "file=@spring-framework-reference.pdf"

# 4. 提问
curl "http://localhost:8080/rag/ask?question=Spring的事务传播机制有哪些?"

返回示例

{
  "question": "Spring的事务传播机制有哪些?",
  "answer": "根据文档,Spring定义了7种事务传播机制:\n1. REQUIRED(默认)...",
  "timestamp": 1704096000000
}

️ 实用技巧

1. 结构化输出(自动解析为Java对象)

// 定义数据结构
record TechArticleSummary(
    String title,
    List<String> keyPoints,
    String targetAudience,
    int estimatedReadingMinutes
) {}

// 自动解析
TechArticleSummary summary = chatClient.prompt()
    .user("总结这篇文章:" + articleContent)
    .call()
    .entity(TechArticleSummary.class);

System.out.println("标题: " + summary.title());
System.out.println("要点: " + String.join(", ", summary.keyPoints()));

2. 函数调用(Tool Calling)

@Component("weatherService")
class WeatherService implements Function<WeatherRequest, WeatherResponse> {
    
    record WeatherRequest(String city) {}
    record WeatherResponse(String city, int temperature, String condition) {}
    
    @Override
    public WeatherResponse apply(WeatherRequest request) {
        // 调用实际的天气API
        return new WeatherResponse(request.city(), 25, "晴朗");
    }
}

// AI会自动判断是否调用工具
ChatClient chatClient = ChatClient.builder()
    .defaultFunctions("weatherService")  // 注册工具
    .build();

String response = chatClient.prompt()
    .user("北京今天天气怎么样?")
    .call()
    .content();
// AI会自动调用weatherService,然后基于返回结果生成自然语言回答

3. 对话历史管理

@Component
public class ConversationService {
    
    private final ChatClient chatClient;
    private final ChatMemory chatMemory;
    
    public ConversationService(ChatClient.Builder builder) {
        // 使用内存存储对话历史(生产环境可用Redis)
        this.chatMemory = new InMemoryChatMemory();
        
        this.chatClient = builder
            .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory))
            .build();
    }
    
    public String chat(String conversationId, String message) {
        return chatClient.prompt()
            .user(message)
            .advisors(a -> a.param("chat_memory_conversation_id", conversationId))
            .call()
            .content();
    }
}

// 使用
conversationService.chat("user123", "我叫张三");
conversationService.chat("user123", "我刚才说我叫什么?");
// 回答:你刚才说你叫张三。

总结与展望

核心观点总结

1. Spring AI ≠ LangChain的Java移植

Spring AI不是简单的框架移植,而是基于Spring设计哲学的原生设计

  • 设计理念不同

    • LangChain:完整的概念体系(Agent/Chain/Memory)
    • Spring AI:简化的抽象层(ChatClient/VectorStore/Advisor)
  • 目标用户不同

    • LangChain:AI研究者、Python开发者
    • Spring AI:企业级Java开发者、Spring生态用户
  • 解决问题不同

    • LangChain:提供完整的AI应用开发框架
    • Spring AI:让现有Spring应用快速集成AI能力

2. 定位明确:企业级Java AI首选

Spring AI在Java AI生态中的定位:

LangChain4j         Spring AI
    ↓                  ↓
功能完整性          企业级特性
学习成本高          学习成本低
需手动配置          自动配置
适合新项目          适合现有项目

Spring AI的核心优势

  • 零学习成本 - Spring开发者直接上手
  • 自动配置 - 添加依赖即可用
  • 企业级特性 - 可观测、安全、事务、测试
  • 生态集成 - 与Spring Boot/Cloud/Data无缝集成

3. 设计哲学:延续Spring的传统

Spring AI完美延续了Spring的核心设计理念:

Spring传统 Spring AI应用
约定优于配置 自动配置、Starter依赖
面向接口编程 ChatModel/VectorStore抽象
模板模式 ChatClient(类似JdbcTemplate)
依赖注入 易测试、易切换
简化复杂性 屏蔽AI API差异

类比总结

JdbcTemplate   →  屏蔽数据库差异
RestTemplate   →  屏蔽HTTP细节
ChatClient     →  屏蔽AI模型差异

框架选型建议

快速决策表

如果你是... 推荐框架 核心理由
Spring应用开发者 ✅ Spring AI 零学习成本、无缝集成
Java开发者(非Spring) LangChain4j 纯Java、功能完整
Python开发者 LangChain 生态最成熟、社区最活跃
需要复杂Agent LangChain/LangChain4j Agent能力更强
专注RAG Spring AI / LlamaIndex Spring AI更易集成
快速原型 ✅ Spring AI 自动配置最快
多模型切换 ✅ Spring AI 统一抽象、配置切换

选型决策树

1. 必须用Java吗?
   ├─ 否 → Python生态
   │   └─ 选LangChain或LlamaIndex
   │
   └─ 是 → 继续判断
       │
       2. 使用Spring框架吗?
          ├─ 是 → Spring AI ⭐⭐⭐⭐⭐
          │   理由:
          │   • 零学习成本
          │   • 自动配置
          │   • 企业级特性完整
          │   • 生态集成最佳
          │
          └─ 否 → LangChain4j ⭐⭐⭐⭐
              理由:
              • 纯Java,无Spring依赖
              • 功能对齐LangChain
              • 适合非Spring项目

未来展望

1. MCP协议支持(已实现)

Spring AI在1.0版本中已经集成了Model Context Protocol (MCP)

// MCP让AI模型能够访问外部资源和工具
@Configuration
public class McpConfig {
    @Bean
    McpClient mcpClient() {
        return McpClient.builder()
            .server("filesystem", new FileSystemMcpServer())
            .server("database", new DatabaseMcpServer())
            .build();
    }
}

MCP的价值

  • 标准化的工具调用协议
  • 安全的资源访问控制
  • 可扩展的服务器生态

2. 多模态能力扩展

未来Spring AI将支持更丰富的模态:

// 图像+文本多模态理解
MultiModalClient client;

Response response = client.prompt()
    .user("这张图片展示了什么架构?")
    .image(new ClassPathResource("architecture.png"))
    .call();

// 语音转文本 + 文本生成 + 文本转语音(完整语音对话)
AudioClient audioClient;
byte[] audioResponse = audioClient.chat(audioInput);

3. Agent生态建设

Spring AI将提供更完善的Agent支持:

@Agent("技术顾问")
public class TechConsultantAgent {
    
    @Tool("搜索文档")
    String searchDocs(String query) { ... }
    
    @Tool("生成代码")
    String generateCode(String requirement) { ... }
    
    @Tool("执行测试")
    TestResult runTest(String code) { ... }
    
    // Agent会自动规划、调用工具、生成答案
}

4. 与Spring Cloud融合

分布式AI应用的编排:

// AI服务的负载均衡
@LoadBalanced
@Bean
ChatClient.Builder chatClientBuilder() { ... }

// AI调用的熔断降级
@HystrixCommand(fallbackMethod = "fallbackResponse")
String chat(String message) { ... }

// 分布式追踪
// AI调用自动纳入Spring Cloud Sleuth追踪

5. 成本优化与治理

// 自动成本控制
@Configuration
public class CostControlConfig {
    @Bean
    ChatClient chatClient(ChatClient.Builder builder) {
        return builder
            .defaultAdvisors(
                new CostLimitAdvisor(maxDailyCost),      // 每日成本上限
                new ModelSelectorAdvisor(costOptimized), // 自动选择性价比模型
                new CacheAdvisor(redisCache)             // 缓存相同问题
            )
            .build();
    }
}

参考资料

官方文档

相关框架

本项目相关文档

社区资源


写在最后

Spring AI的出现,标志着企业级Java应用的AI时代正式到来

它不是对Python框架的简单移植,而是基于25年Spring设计哲学的重新思考与原生设计。对于数百万Spring开发者来说,Spring AI让AI集成变得:

  • 自然 - 熟悉的API、熟悉的配置、熟悉的部署
  • 简单 - 自动配置、零学习成本、快速上手
  • 可靠 - 企业级特性、生产就绪、可观测可维护

如果你是Spring开发者,想要为应用集成AI能力,Spring AI是当之无愧的首选。


本文档由Manus创作,基于Spring AI 1.0.3版本官方文档及实践经验整理。
最后更新:2025年10月