目录
-
[RAG 检索增强生成](#RAG 检索增强生成)
-
[MCP 模型上下文协议](#MCP 模型上下文协议)
-
[Spring Boot 自动配置](#Spring Boot 自动配置)
1. 项目概览
1.1 项目定位
Spring AI 是 Spring 生态系统针对人工智能领域的扩展项目,其设计目标是:
-
可移植性:提供统一的 API 抽象,支持不同 AI 提供商的切换
-
模块化设计:各个功能组件松耦合,可独立使用
-
POJO 编程模型:延续 Spring 传统,使用简单的 Java 对象构建 AI 应用
-
与 Spring 生态无缝集成:支持 Spring Boot 自动配置、依赖注入等特性
1.2 项目统计
| 指标 | 数据 |
|---|---|
| 版本 | 1.1.4 |
| Maven 模块数 | 180+ |
| 支持的模型提供商 | 20+ |
| 支持的向量数据库 | 19+ |
| 核心编程语言 | Java 17+ |
1.3 模块分类
spring-ai-1.1.4/ ├── 核心抽象层 │ ├── spring-ai-model # 模型核心抽象 │ ├── spring-ai-client-chat # 聊天客户端 │ ├── spring-ai-vector-store # 向量存储抽象 │ ├── spring-ai-commons # 公共组件 │ └── spring-ai-rag # RAG 框架 ├── 模型实现层 │ └── models/ # 20+ AI 提供商实现 │ ├── spring-ai-openai │ ├── spring-ai-zhipuai │ ├── spring-ai-azure-openai │ └── ... ├── 向量存储实现层 │ └── vector-stores/ # 19+ 向量数据库实现 │ ├── spring-ai-pgvector-store │ ├── spring-ai-milvus-store │ ├── spring-ai-elasticsearch-store │ └── ... ├── 内存存储层 │ └── memory/repository/ # 聊天内存存储实现 ├── 文档读取层 │ └── document-readers/ # 文档解析 ├── MCP 层 │ └── mcp/ # Model Context Protocol ├── Spring Boot 集成层 │ ├── auto-configurations/ # 自动配置 │ └── spring-ai-spring-boot-starters/ # Starter └── 其他工具 ├── spring-ai-retry # 重试机制 ├── spring-ai-test # 测试工具 └── spring-ai-docs # 文档
2. 整体架构设计
2.1 架构全景图
2.2 核心设计原则
2.2.1 接口隔离原则 (ISP)
Spring AI 将功能拆分为细粒度的接口:
java
// 基础模型接口 - 最抽象的调用契约
public interface Model<TReq extends ModelRequest<?>, TRes extends ModelResponse<?>> {
TRes call(TReq request);
}
// 聊天模型接口 - 针对对话场景的扩展
public interface ChatModel extends Model<Prompt, ChatResponse>, StreamingChatModel {
String call(String message);
ChatResponse call(Prompt prompt);
Flux<ChatResponse> stream(Prompt prompt);
}
// 嵌入模型接口 - 专门处理文本向量化
public interface EmbeddingModel extends Model<EmbeddingRequest, EmbeddingResponse> {
float[] embed(String text);
float[] embed(Document document);
}
// 图像模型接口 - 处理图像生成
public interface ImageModel extends Model<ImagePrompt, ImageResponse> {
ImageResponse call(ImagePrompt prompt);
}
2.2.2 构建器模式 (Builder Pattern)
几乎所有配置对象都使用构建器模式:
java
// ChatClient 构建示例
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultSystem("你是一个 helpful 助手")
.defaultOptions(ChatOptions.builder()
.temperature(0.7)
.maxTokens(1000)
.build())
.build();
// VectorStore 构建示例
VectorStore vectorStore = PgVectorStore.builder(embeddingModel)
.dimensions(1536)
.distanceType(PgVectorStore.PgDistanceType.COSINE_DISTANCE)
.initializeSchema(true)
.build();
2.2.3 顾问模式 (Advisor Pattern)
java
Advisor 是 Spring AI 的核心扩展机制:
// Advisor 接口定义
public interface Advisor {
// 在调用模型前执行
ChatClientRequest before(ChatClientRequest request, AdvisorChain chain);
// 在获得响应后执行
ChatClientResponse after(ChatClientResponse response, AdvisorChain chain);
}
// 常见 Advisor 实现
- MessageChatMemoryAdvisor // 聊天历史管理
- QuestionAnswerAdvisor // RAG问答增强
- SimpleLoggerAdvisor // 日志记录
- SafeGuardAdvisor // 内容安全
3. 核心模块详解
3.1 spring-ai-model 模块
这是整个 Spring AI 的基石模块,定义了所有 AI 模型的抽象接口。
3.1.1 核心接口层次结构
3.1.2 消息模型详解
Spring AI 定义了完整的消息类型体系:
java
// 基础消息接口
public interface Message extends Content {
MessageType getMessageType();
}
// 消息类型枚举
public enum MessageType {
USER("user"), // 用户消息
ASSISTANT("assistant"), // 助手消息
SYSTEM("system"), // 系统消息
TOOL("tool"); // 工具响应消息
}
// 具体消息实现
public class UserMessage extends AbstractMessage {
private final List<Media> media; // 支持多模态
private final String text;
}
public class AssistantMessage extends AbstractMessage {
private final List<ToolCall> toolCalls; // 工具调用请求
private final String text;
}
public class ToolResponseMessage extends AbstractMessage {
private final String toolName;
private final String responseData; // 工具执行结果
}
public class SystemMessage extends AbstractMessage {
private final String text;
}
设计亮点:
-
支持多模态内容(文本 + 图片 + 音频)
-
工具调用采用请求-响应模式
-
所有消息都是不可变对象(Immutable)
3.1.3 Prompt 设计
java
// Prompt 是发送给模型的完整上下文
public class Prompt implements ModelRequest<List<Message>> {
private final List<Message> instructions; // 消息列表
private final ChatOptions options; // 模型参数
}
// 使用示例
Prompt prompt = new Prompt(
List.of(
new SystemMessage("你是一个专业程序员"),
new UserMessage("解释 Spring 的依赖注入")
),
ChatOptions.builder()
.temperature(0.3) // 创造性较低,更准确
.build()
);
3.1.4 工具调用架构
工具调用是现代 AI 应用的核心能力:
java
// 工具回调接口 - 模型可触发的功能
public interface ToolCallback {
ToolDefinition getToolDefinition(); // 工具元数据
ToolMetadata getToolMetadata(); // 执行配置
String call(String toolInput); // 同步执行
String call(String toolInput, ToolContext context); // 带上下文执行
}
// 工具定义 - 告诉模型如何调用
public interface ToolDefinition {
String name(); // 工具名称
String description(); // 工具描述(模型据此决定是否调用)
String inputSchema(); // JSON Schema 参数定义
}
// 工具调用管理器
public interface ToolCallingManager {
List<ToolDefinition> resolveToolDefinitions(ToolCallingChatOptions options);
ToolExecutionResult executeToolCalls(Prompt prompt, ChatResponse response);
}
工具调用流程:
3.2 spring-ai-client-chat 模块
这是面向开发者的高层 API,提供流畅的 DSL 风格接口。
3.2.1 ChatClient 架构
java
// 入口接口
public interface ChatClient {
// 创建方法
static ChatClient create(ChatModel chatModel);
static Builder builder(ChatModel chatModel);
// 开始构建请求
ChatClientRequestSpec prompt();
ChatClientRequestSpec prompt(String content);
ChatClientRequestSpec prompt(Prompt prompt);
// 变异构建
Builder mutate();
}
3.2.2 流畅 API 设计
java
// 典型使用模式
String response = chatClient.prompt()
.system("你是一个 helpful 助手") // 系统提示
.user("讲一个关于 Spring 的笑话") // 用户输入
.options(options -> options.temperature(0.8)) // 参数设置
.advisors(new SimpleLoggerAdvisor()) // 添加 Advisor
.tools(new DateTimeTools()) // 注册工具
.call() // 执行调用
.content(); // 获取内容
// 结构化输出
ActorFilms actorFilms = chatClient.prompt()
.user("告诉我 Tom Hanks 的电影")
.call()
.entity(ActorFilms.class); // 自动映射到 POJO
// 流式响应
chatClient.prompt()
.user("写一首关于 Java 的诗")
.stream()
.content()
.subscribe(System.out::print);
3.2.3 Advisor 机制深度解析
Advisor 是 Spring AI 最强大的扩展点:
java
// Advisor 基础接口
public interface CallAdvisor extends Advisor {
ChatClientRequest before(ChatClientRequest request, CallAdvisorChain chain);
ChatClientResponse after(ChatClientResponse response, CallAdvisorChain chain);
}
// 核心 Advisor 实现
// 1. 聊天记忆 Advisor
public class MessageChatMemoryAdvisor implements CallAdvisor {
private final ChatMemory chatMemory; // 内存存储
private final String conversationId; // 会话ID
@Override
public ChatClientRequest before(ChatClientRequest request, CallAdvisorChain chain) {
// 1. 加载历史消息
List<Message> history = chatMemory.get(conversationId, 10);
// 2. 将历史添加到请求
return request.mutate()
.messages(history)
.build();
}
@Override
public ChatClientResponse after(ChatClientResponse response, CallAdvisorChain chain) {
// 3. 保存新消息到内存
chatMemory.add(conversationId, response.getResult().getOutput());
return response;
}
}
// 2. RAG Advisor
public class QuestionAnswerAdvisor implements CallAdvisor {
private final VectorStore vectorStore;
private final SearchRequest searchRequest;
@Override
public ChatClientRequest before(ChatClientRequest request, CallAdvisorChain chain) {
// 1. 将用户问题向量化
String userText = request.prompt().getUserMessage().getText();
// 2. 检索相关文档
List<Document> documents = vectorStore.similaritySearch(
SearchRequest.query(userText).withTopK(5)
);
// 3. 将文档注入系统提示
String context = documents.stream()
.map(Document::getText)
.collect(Collectors.joining("\n"));
return request.mutate()
.system(s -> s.text("基于以下上下文回答:\n" + context))
.build();
}
}
Advisor 执行链:
3.3 spring-ai-vector-store 模块
向量存储是 RAG 应用的基础设施。
3.3.1 VectorStore 接口设计
java
public interface VectorStore extends DocumentWriter, VectorStoreRetriever {
// 写入文档(自动向量化)
void add(List<Document> documents);
// 根据 ID 删除
void delete(List<String> idList);
// 根据过滤条件删除
void delete(Filter.Expression filterExpression);
// 相似度搜索
List<Document> similaritySearch(SearchRequest request);
// Builder 模式支持
interface Builder<T extends Builder<T>> {
T observationRegistry(ObservationRegistry registry);
T batchingStrategy(BatchingStrategy strategy);
VectorStore build();
}
}
3.3.2 搜索请求构建
java
SearchRequest request = SearchRequest.builder()
.query("Spring Security 认证流程") // 查询文本
.topK(5) // 返回前5个结果
.similarityThreshold(0.7) // 相似度阈值
.filterExpression("category == 'tech' && year >= 2023") // 元数据过滤
.build();
List<Document> results = vectorStore.similaritySearch(request);
3.3.3 过滤器表达式
Spring AI 提供了 SQL 风格的过滤器表达式:
// 支持的运算符 - 比较:==、!=、>、>=、<、<= - 逻辑:AND、OR、NOT - 集合:IN、NIN // 示例 "country == 'USA' AND year >= 2020" "category IN ['tech', 'science']" "NOT (author == 'unknown')" "price > 100 AND (category == 'book' OR category == 'ebook')"
实现原理:使用 ANTLR4 解析表达式并转换为各数据库的查询语法。
3.3.4 SimpleVectorStore 实现
内存级向量存储,适合测试:
java
public class SimpleVectorStore extends AbstractObservationVectorStore {
private final Map<String, SimpleVectorStoreContent> store = new ConcurrentHashMap<>();
@Override
public void doAdd(List<Document> documents) {
for (Document doc : documents) {
float[] embedding = embeddingModel.embed(doc);
store.put(doc.getId(), new SimpleVectorStoreContent(
doc.getId(),
doc.getText(),
doc.getMetadata(),
embedding
));
}
}
@Override
public List<Document> doSimilaritySearch(SearchRequest request) {
float[] queryEmbedding = embeddingModel.embed(request.getQuery());
return store.values().stream()
.map(content -> new AbstractMap.SimpleEntry<>(
content,
calculateCosineSimilarity(queryEmbedding, content.getEmbedding())
))
.filter(entry -> entry.getValue() >= request.getSimilarityThreshold())
.sorted(Map.Entry.<SimpleVectorStoreContent, Double>comparingByValue().reversed())
.limit(request.getTopK())
.map(entry -> new Document(
entry.getKey().getId(),
entry.getKey().getText(),
entry.getKey().getMetadata()
))
.collect(Collectors.toList());
}
}
3.4 spring-ai-commons 模块
包含所有模块共享的基础组件。
3.4.1 Document 类
java
public class Document {
private final String id; // 唯一标识
private final String text; // 文本内容
private final Media media; // 媒体内容(多模态)
private final Map<String, Object> metadata; // 元数据
private final Double score; // 相似度分数
// 支持文本或媒体,但不能同时存在
public boolean isText() { return text != null; }
public boolean isMedia() { return media != null; }
}
3.4.2 内容转换器
java
// 结构化输出转换
public interface StructuredOutputConverter<T> {
String getFormat(); // 告诉模型输出格式
T convert(String text); // 解析模型输出
}
// Bean 输出转换器 - 自动映射到 POJO
public class BeanOutputConverter<T> implements StructuredOutputConverter<T> {
private final Class<T> targetClass;
private final ObjectMapper objectMapper;
@Override
public String getFormat() {
// 生成 JSON Schema 提示模型
return JsonSchemaGenerator.generateFor(targetClass);
}
@Override
public T convert(String text) {
return objectMapper.readValue(text, targetClass);
}
}
// 使用示例
BeanOutputConverter<ActorFilms> converter =
new BeanOutputConverter<>(ActorFilms.class);
String jsonResponse = chatClient.prompt()
.user(u -> u.text("列出 Tom Hanks 的电影"))
.call()
.content();
ActorFilms result = converter.convert(jsonResponse);
4. 模型集成层
4.1 模型实现架构
每个模型提供商的实现都遵循统一架构:
4.2 OpenAI 实现详解
4.2.1 OpenAiApi - 底层 HTTP 客户端
java
public class OpenAiApi {
private final RestClient restClient;
// 聊天完成 API
public ResponseEntity<ChatCompletion> chatCompletionEntity(
ChatCompletionRequest request,
MultiValueMap<String, String> additionalHttpHeaders) {
return restClient.post()
.uri("/v1/chat/completions")
.headers(headers -> headers.addAll(additionalHttpHeaders))
.body(request)
.retrieve()
.toEntity(ChatCompletion.class);
}
// 流式响应
public Flux<ChatCompletionChunk> chatCompletionStream(
ChatCompletionRequest request) {
return webClient.post()
.uri("/v1/chat/completions")
.bodyValue(request)
.retrieve()
.bodyToFlux(ChatCompletionChunk.class);
}
}
// 请求/响应 DTO
public record ChatCompletionRequest(
String model,
List<ChatCompletionMessage> messages,
Double temperature,
Integer maxTokens,
List<FunctionTool> tools,
ResponseFormat responseFormat
) {}
public record ChatCompletion(
String id,
List<Choice> choices,
Usage usage
) {
public record Choice(
int index,
ChatCompletionMessage message,
String finishReason
) {}
}
4.2.2 OpenAiChatModel - 高层封装
java
public class OpenAiChatModel implements ChatModel {
private final OpenAiApi openAiApi;
private final OpenAiChatOptions defaultOptions;
private final ToolCallingManager toolCallingManager;
private final RetryTemplate retryTemplate;
private final ObservationRegistry observationRegistry;
@Override
public ChatResponse call(Prompt prompt) {
// 1. 合并默认选项和运行时选项
Prompt requestPrompt = buildRequestPrompt(prompt);
// 2. 创建观测上下文
ChatModelObservationContext context = ChatModelObservationContext.builder()
.prompt(requestPrompt)
.provider(OpenAiApiConstants.PROVIDER_NAME)
.build();
// 3. 使用 Observation 包装调用
return ChatModelObservationDocumentation.CHAT_MODEL_OPERATION
.observation(observationConvention, DEFAULT_OBSERVATION_CONVENTION,
() -> context, observationRegistry)
.observe(() -> {
// 4. 执行重试逻辑
ResponseEntity<ChatCompletion> response = retryTemplate.execute(
ctx -> openAiApi.chatCompletionEntity(
createRequest(requestPrompt, false),
getAdditionalHttpHeaders(requestPrompt)
)
);
// 5. 处理工具调用
ChatCompletion completion = response.getBody();
if (hasToolCalls(completion)) {
return handleToolCalls(requestPrompt, completion);
}
// 6. 转换为统一响应格式
return toChatResponse(response);
});
}
// 流式响应实现
@Override
public Flux<ChatResponse> stream(Prompt prompt) {
ChatCompletionRequest request = createRequest(buildRequestPrompt(prompt), true);
return openAiApi.chatCompletionStream(request)
.map(this::toChatResponseChunk)
.concatMap(response -> {
// 聚合流式响应
if (isComplete(response)) {
return Flux.just(response);
}
return Flux.just(response);
});
}
}
4.3 智谱 AI (ZhiPuAI) 实现
智谱 AI 是国内主流的大模型提供商,Spring AI 提供了完整支持。
4.3.1 实现结构
java
// 与 OpenAI 结构类似,但适配智谱 API
public class ZhiPuAiChatModel implements ChatModel {
private final ZhiPuAiApi zhiPuAiApi;
private final ZhiPuAiChatOptions defaultOptions;
@Override
public ChatResponse call(Prompt prompt) {
ZhiPuAiApi.ChatCompletionRequest request = createRequest(prompt);
ResponseEntity<ZhiPuAiApi.ChatCompletion> response =
retryTemplate.execute(ctx -> zhiPuAiApi.chatCompletionEntity(request));
return toChatResponse(response.getBody());
}
}
// 智谱特有选项
public class ZhiPuAiChatOptions implements ChatOptions {
private String model; // 模型名称:glm-4、glm-4-flash 等
private Double temperature; // 温度参数
private Integer maxTokens; // 最大 token 数
private Boolean stream; // 是否流式
private List<FunctionCallback> tools; // 工具列表
}
4.4 其他模型支持
Spring AI 1.1.4 支持的模型提供商:
| 提供商 | 模块 | 支持功能 |
|---|---|---|
| OpenAI | spring-ai-openai | 聊天、嵌入、图像、语音、审核 |
| Azure OpenAI | spring-ai-azure-openai | 聊天、嵌入、图像 |
| 智谱 AI | spring-ai-zhipuai | 聊天、嵌入、图像 |
| Anthropic | spring-ai-anthropic | 聊天 |
| Mistral AI | spring-ai-mistral-ai | 聊天、嵌入 |
| Ollama | spring-ai-ollama | 聊天、嵌入 |
| HuggingFace | spring-ai-huggingface | 嵌入 |
| Google Vertex AI | spring-ai-vertex-ai-gemini | 聊天、嵌入 |
| Amazon Bedrock | spring-ai-bedrock | 聊天、嵌入 |
| DeepSeek | spring-ai-deepseek | 聊天 |
| MiniMax | spring-ai-minimax | 聊天、嵌入 |
| ... | ... | ... |
5. 向量存储系统
5.1 支持的向量数据库
Spring AI 支持 19 种向量数据库:
关系型数据库扩展: - PostgreSQL + pgvector - MariaDB - Oracle 专用向量数据库: - Milvus / Zilliz - Pinecone - Qdrant - Weaviate - Chroma 通用数据库向量扩展: - Elasticsearch - OpenSearch - Redis - MongoDB Atlas - Neo4j - Cassandra - Azure Cosmos DB 云服务: - Azure AI Search - Couchbase - GemFire - Typesense - HANA DB
5.2 PGVector 实现详解
PostgreSQL + pgvector 是最流行的向量存储方案:
java
public class PgVectorStore extends AbstractObservationVectorStore {
private final JdbcTemplate jdbcTemplate;
private final int dimensions;
private final PgDistanceType distanceType;
private final boolean initializeSchema;
@Override
public void doAdd(List<Document> documents) {
for (Document document : documents) {
float[] embedding = embeddingModel.embed(document);
jdbcTemplate.update(
"INSERT INTO vector_store (id, content, metadata, embedding) " +
"VALUES (?, ?, ?::jsonb, ?) " +
"ON CONFLICT (id) DO UPDATE SET " +
"content = EXCLUDED.content, " +
"metadata = EXCLUDED.metadata, " +
"embedding = EXCLUDED.embedding",
document.getId(),
document.getText(),
toJson(document.getMetadata()),
toPgVector(embedding)
);
}
}
@Override
public List<Document> doSimilaritySearch(SearchRequest request) {
float[] queryEmbedding = embeddingModel.embed(request.getQuery());
String sql = String.format(
"SELECT id, content, metadata, embedding %s as distance " +
"FROM vector_store " +
"WHERE embedding %s ?::vector " +
"%s" + // 过滤条件
"ORDER BY embedding %s ?::vector " +
"LIMIT ?",
distanceType.getOperator(),
distanceType.getOperator(),
buildFilterClause(request.getFilterExpression()),
distanceType.getOperator()
);
return jdbcTemplate.query(sql, documentRowMapper,
toPgVector(queryEmbedding),
toPgVector(queryEmbedding),
request.getTopK()
);
}
}
5.3 Milvus 实现
java
public class MilvusVectorStore extends AbstractObservationVectorStore {
private final MilvusServiceClient milvusClient;
private final String collectionName;
@Override
public void doAdd(List<Document> documents) {
List<String> ids = new ArrayList<>();
List<String> contents = new ArrayList<>();
List<JSONObject> metadata = new ArrayList<>();
List<List<Float>> vectors = new ArrayList<>();
for (Document doc : documents) {
ids.add(doc.getId());
contents.add(doc.getText());
metadata.add(new JSONObject(doc.getMetadata()));
vectors.add(toList(embeddingModel.embed(doc)));
}
milvusClient.insert(InsertParam.newBuilder()
.withCollectionName(collectionName)
.withFields(List.of(
new InsertParam.Field("id", ids),
new InsertParam.Field("content", contents),
new InsertParam.Field("metadata", metadata),
new InsertParam.Field("embedding", vectors)
))
.build()
);
}
}
6. RAG 检索增强生成
6.1 RAG 架构设计
Spring AI 的 RAG 实现遵循模块化和可扩展原则:
6.2 RetrievalAugmentationAdvisor
这是 RAG 的核心实现类:
java
public final class RetrievalAugmentationAdvisor implements BaseAdvisor {
private final List<QueryTransformer> queryTransformers;
private final QueryExpander queryExpander;
private final DocumentRetriever documentRetriever;
private final DocumentJoiner documentJoiner;
private final List<DocumentPostProcessor> documentPostProcessors;
private final QueryAugmenter queryAugmenter;
@Override
public ChatClientRequest before(ChatClientRequest request, AdvisorChain chain) {
// 0. 创建 Query 对象
Query originalQuery = Query.builder()
.text(request.prompt().getUserMessage().getText())
.history(request.prompt().getInstructions())
.build();
// 1. 查询转换(如:翻译、压缩历史)
Query transformedQuery = originalQuery;
for (var transformer : queryTransformers) {
transformedQuery = transformer.apply(transformedQuery);
}
// 2. 查询扩展(如:生成多个相关查询)
List<Query> expandedQueries = queryExpander != null
? queryExpander.expand(transformedQuery)
: List.of(transformedQuery);
// 3. 并行检索文档
Map<Query, List<List<Document>>> documentsForQuery = expandedQueries.stream()
.map(query -> CompletableFuture.supplyAsync(
() -> getDocumentsForQuery(query), taskExecutor))
.toList()
.stream()
.map(CompletableFuture::join)
.collect(Collectors.toMap(Map.Entry::getKey, entry -> List.of(entry.getValue())));
// 4. 合并文档
List<Document> documents = documentJoiner.join(documentsForQuery);
// 5. 后处理(如:重排序、去重)
for (var processor : documentPostProcessors) {
documents = processor.process(originalQuery, documents);
}
// 6. 查询增强(将文档注入提示)
Query augmentedQuery = queryAugmenter.augment(originalQuery, documents);
// 7. 更新请求
return request.mutate()
.prompt(request.prompt().augmentUserMessage(augmentedQuery.text()))
.context(context -> context.put(DOCUMENT_CONTEXT, documents))
.build();
}
}
6.3 查询转换器 (QueryTransformer)
java
// 查询转换器接口
public interface QueryTransformer extends Function<Query, Query> {}
// 1. 重写查询 - 优化问题表达
public class RewriteQueryTransformer implements QueryTransformer {
private final ChatClient chatClient;
@Override
public Query apply(Query query) {
String rewritten = chatClient.prompt()
.system("重写以下查询,使其更清晰、更具体")
.user(query.text())
.call()
.content();
return query.mutate().text(rewritten).build();
}
}
// 2. 翻译查询 - 支持多语言
public class TranslationQueryTransformer implements QueryTransformer {
private final ChatClient chatClient;
private final String targetLanguage;
@Override
public Query apply(Query query) {
String translated = chatClient.prompt()
.system("将查询翻译成" + targetLanguage)
.user(query.text())
.call()
.content();
return query.mutate().text(translated).build();
}
}
// 3. 压缩历史 - 长对话优化
public class CompressionQueryTransformer implements QueryTransformer {
@Override
public Query apply(Query query) {
// 压缩对话历史,保留关键信息
List<Message> compressedHistory = compressHistory(query.history());
return query.mutate().history(compressedHistory).build();
}
}
6.4 文档检索器 (DocumentRetriever)
java
// 基于向量存储的检索器
public class VectorStoreDocumentRetriever implements DocumentRetriever {
private final VectorStore vectorStore;
private final SearchRequest searchRequest;
@Override
public List<Document> retrieve(Query query) {
SearchRequest request = SearchRequest.builder()
.query(query.text())
.topK(searchRequest.getTopK())
.similarityThreshold(searchRequest.getSimilarityThreshold())
.filterExpression(searchRequest.getFilterExpression())
.build();
return vectorStore.similaritySearch(request);
}
}
6.5 查询增强器 (QueryAugmenter)
java
// 上下文查询增强器
public class ContextualQueryAugmenter implements QueryAugmenter {
@Override
public Query augment(Query query, List<Document> documents) {
if (documents.isEmpty()) {
return query; // 无文档时不增强
}
String context = documents.stream()
.map(doc -> String.format("[Document ID: %s]\n%s", doc.getId(), doc.getText()))
.collect(Collectors.joining("\n\n"));
String augmentedText = String.format("""
基于以下上下文信息回答问题:
%s
问题:%s
如果上下文中没有相关信息,请说明你不知道。
""", context, query.text());
return query.mutate().text(augmentedText).build();
}
}
7. MCP 模型上下文协议
7.1 MCP 概述
Model Context Protocol (MCP) 是 Anthropic 推出的开放协议,用于标准化 AI 模型与外部工具、数据源的集成。
7.2 MCP 架构
7.3 MCP 核心组件
java
// MCP 工具回调
public class SyncMcpToolCallback implements ToolCallback {
private final McpSyncClient mcpClient;
private final Tool tool;
@Override
public ToolDefinition getToolDefinition() {
return ToolDefinition.builder()
.name(tool.name())
.description(tool.description())
.inputSchema(tool.inputSchema())
.build();
}
@Override
public String call(String toolInput) {
CallToolResult result = mcpClient.callTool(
new CallToolRequest(tool.name(), parseJson(toolInput))
);
return serializeResult(result);
}
}
// 异步版本
public class AsyncMcpToolCallback implements ToolCallback {
private final McpAsyncClient mcpClient;
@Override
public String call(String toolInput) {
// 阻塞等待异步结果
return mcpClient.callTool(request)
.block()
.toString();
}
}
7.4 MCP 注解支持
Spring AI 提供了基于注解的 MCP 工具定义:
java
@Component
public class WeatherTools {
@Tool(description = "获取指定城市的天气信息")
public WeatherInfo getWeather(
@ToolParam(description = "城市名称,如:北京") String city,
@ToolParam(description = "日期,格式:yyyy-MM-dd") String date) {
// 实现逻辑
return weatherService.fetch(city, date);
}
}
8. 工具调用机制
8.1 工具调用架构
8.2 工具定义与实现
java
// 方式1:使用 Function
FunctionToolCallback.builder("getWeather", (WeatherRequest request) -> {
return weatherService.getWeather(request.city(), request.date());
})
.description("获取城市天气")
.inputSchema(WeatherRequest.class)
.build();
// 方式2:使用方法引用
Method method = WeatherService.class.getMethod("getWeather", String.class, String.class);
MethodToolCallback.builder(method, weatherService)
.description("获取城市天气")
.build();
// 方式3:Spring Bean 自动发现
@Bean
public ToolCallbackProvider weatherTools(WeatherService service) {
return MethodToolCallbackProvider.builder()
.toolObjects(service)
.build();
}
8.3 ToolCallingManager 实现
java
public class DefaultToolCallingManager implements ToolCallingManager {
private final ToolCallbackResolver toolCallbackResolver;
private final ToolExecutionExceptionProcessor exceptionProcessor;
@Override
public ToolExecutionResult executeToolCalls(Prompt prompt, ChatResponse chatResponse) {
AssistantMessage assistantMessage = chatResponse.getResult().getOutput();
List<ToolResponseMessage> toolResponseMessages = new ArrayList<>();
for (ToolCall toolCall : assistantMessage.getToolCalls()) {
try {
// 1. 解析工具调用
String toolName = toolCall.name();
String toolInput = toolCall.arguments();
// 2. 查找工具
ToolCallback toolCallback = toolCallbackResolver.resolve(toolName);
if (toolCallback == null) {
throw new IllegalArgumentException("Tool not found: " + toolName);
}
// 3. 执行工具
String result = toolCallback.call(toolInput);
// 4. 构造工具响应
toolResponseMessages.add(new ToolResponseMessage(
result, toolName, toolCall.id()
));
} catch (Exception e) {
// 5. 异常处理
String errorResult = exceptionProcessor.process(e);
toolResponseMessages.add(new ToolResponseMessage(
errorResult, toolCall.name(), toolCall.id()
));
}
}
return ToolExecutionResult.builder()
.prompt(prompt) // 包含原对话 + 工具响应
.build();
}
}
9. Spring Boot 自动配置
9.1 自动配置架构
Spring AI 为每个模型和向量存储提供独立的自动配置模块:
auto-configurations/ ├── models/ │ ├── spring-ai-autoconfigure-model-openai │ ├── spring-ai-autoconfigure-model-zhipuai │ └── ... ├── vector-stores/ │ ├── spring-ai-autoconfigure-vector-store-pgvector │ ├── spring-ai-autoconfigure-vector-store-milvus │ └── ... └── mcp/ ├── spring-ai-autoconfigure-mcp-client-common └── spring-ai-autoconfigure-mcp-server-common
9.2 OpenAI 自动配置示例
java
@Configuration
@ConditionalOnClass(OpenAiApi.class)
@EnableConfigurationProperties(OpenAiChatProperties.class)
public class OpenAiAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public OpenAiApi openAiApi(OpenAiConnectionProperties connectionProperties) {
return OpenAiApi.builder()
.apiKey(connectionProperties.getApiKey())
.baseUrl(connectionProperties.getBaseUrl())
.build();
}
@Bean
@ConditionalOnMissingBean
public OpenAiChatModel openAiChatModel(
OpenAiApi openAiApi,
OpenAiChatProperties chatProperties,
ToolCallingManager toolCallingManager,
ObservationRegistry observationRegistry) {
return new OpenAiChatModel(
openAiApi,
chatProperties.getOptions(),
toolCallingManager,
RetryUtils.DEFAULT_RETRY_TEMPLATE,
observationRegistry
);
}
}
// 配置属性
@ConfigurationProperties("spring.ai.openai")
public class OpenAiChatProperties {
private String apiKey;
private String baseUrl = "https://api.openai.com";
private ChatOptions options = new ChatOptions();
}
9.3 Starter 模块
Starter 模块将自动配置和依赖整合:
XML
<!-- spring-ai-starter-model-openai/pom.xml -->
<dependencies>
<!-- 自动配置 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-autoconfigure-model-openai</artifactId>
</dependency>
<!-- 核心实现 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai</artifactId>
</dependency>
<!-- Spring Boot 自动配置支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
9.4 应用配置示例
bash
# application.yml
spring:
ai:
# OpenAI 配置
openai:
api-key: ${OPENAI_API_KEY}
base-url: https://api.openai.com
chat:
options:
model: gpt-4
temperature: 0.7
max-tokens: 2000
# 智谱 AI 配置
zhipuai:
api-key: ${ZHIPUAI_API_KEY}
chat:
options:
model: glm-4
temperature: 0.7
# 向量存储配置
vectorstore:
pgvector:
index-type: hnsw
distance-type: cosine_distance
dimensions: 1536
initialize-schema: true
10. 最佳实践与设计模式
10.1 推荐项目结构
my-spring-ai-app/ ├── src/main/java/com/example/ai/ │ ├── config/ │ │ ├── AIConfig.java # AI 模型配置 │ │ └── VectorStoreConfig.java # 向量存储配置 │ ├── controller/ │ │ └── ChatController.java # REST API │ ├── service/ │ │ ├── ChatService.java # 聊天服务 │ │ ├── RAGService.java # RAG 服务 │ │ └── EmbeddingService.java # 嵌入服务 │ ├── tools/ │ │ └── WeatherTools.java # 工具定义 │ └── advisor/ │ └── CustomAdvisor.java # 自定义 Advisor ├── src/main/resources/ │ ├── application.yml │ └── prompts/ # 提示模板 │ ├── system-prompt.st │ └── rag-context.st └── pom.xml
10.2 配置类最佳实践
java
@Configuration
public class AIConfig {
@Bean
public ChatClient chatClient(ChatModel chatModel) {
return ChatClient.builder(chatModel)
.defaultSystem("你是一个专业的技术助手")
.defaultOptions(ChatOptions.builder()
.temperature(0.7)
.maxTokens(2000)
.build())
.build();
}
@Bean
public VectorStore vectorStore(
EmbeddingModel embeddingModel,
JdbcTemplate jdbcTemplate) {
return PgVectorStore.builder(embeddingModel)
.jdbcTemplate(jdbcTemplate)
.dimensions(1536)
.initializeSchema(true)
.build();
}
}
10.3 RAG 完整示例
java
@Service
public class RAGService {
private final ChatClient chatClient;
private final VectorStore vectorStore;
public String chatWithDocuments(String query) {
return chatClient.prompt()
.advisors(new QuestionAnswerAdvisor(
vectorStore,
SearchRequest.defaults().withTopK(5)
))
.user(query)
.call()
.content();
}
}
// 更复杂的 RAG 配置
@Bean
public RetrievalAugmentationAdvisor retrievalAugmentationAdvisor(
VectorStore vectorStore,
ChatClient chatClient) {
return RetrievalAugmentationAdvisor.builder()
// 查询转换
.queryTransformers(new TranslationQueryTransformer(chatClient, "zh"))
// 查询扩展
.queryExpander(new MultiQueryExpander(chatClient, 3))
// 文档检索
.documentRetriever(VectorStoreDocumentRetriever.builder()
.vectorStore(vectorStore)
.searchRequest(SearchRequest.defaults().withTopK(5))
.build())
// 查询增强
.queryAugmenter(ContextualQueryAugmenter.builder()
.promptTemplate("基于以下内容回答:\n\n{context}\n\n问题:{query}")
.build())
.build();
}
10.4 错误处理与重试
java
@Configuration
public class RetryConfig {
@Bean
public RetryTemplate aiRetryTemplate() {
return RetryTemplate.builder()
.maxAttempts(3)
.fixedBackoff(1000)
.retryOn(TransientAiException.class)
.build();
}
}
@Service
public class RobustChatService {
private final ChatClient chatClient;
private final RetryTemplate retryTemplate;
public String chatWithRetry(String message) {
return retryTemplate.execute(context -> {
try {
return chatClient.prompt()
.user(message)
.call()
.content();
} catch (Exception e) {
// 判断是否为可重试错误
if (isTransientError(e)) {
throw new TransientAiException(e);
}
throw e;
}
});
}
}
10.5 观测与监控
java
@Configuration
public class ObservationConfig {
@Bean
public ChatClientObservationConvention customObservationConvention() {
return context -> {
// 自定义观测标签
return KeyValues.of(
KeyValue.of("ai.application", "my-app"),
KeyValue.of("ai.environment", "production")
);
};
}
}
// 使用 Micrometer 观测
chatClient.prompt()
.observationRegistry(observationRegistry)
.user("Hello")
.call();
总结
Spring AI 1.1.4 是一个设计精良、功能丰富的 AI 应用开发框架。其核心优势包括:
-
统一的 API 抽象:支持 20+ 模型提供商的切换,代码可移植性强
-
模块化架构:各组件松耦合,可按需使用
-
Spring 原生集成:充分利用 Spring Boot 的自动配置和依赖注入
-
强大的扩展机制:Advisor 模式提供了灵活的扩展点
-
完整的 RAG 支持:从文档处理到检索增强的完整链路
-
企业级特性:内置重试、观测、监控等企业级功能
通过深入理解其架构设计和源码实现,开发者可以更好地利用 Spring AI 构建高质量的 AI 应用。
参考资料:
