Spring AI 2.1.0-RC2 现已发布
我谨代表 Spring AI 团队和所有贡献者,很高兴宣布 Spring AI 2.1.0-RC2 已发布,并可从 Maven Central 获取!
2.1.0-RC2 基于 2.1.0-RC1 构建,并交付了 DecisionModel——一个用于类型化的“是/否”、选择和评分决策的新 API,以及首批基于它构建的功能。它还新增了工具调用增量流式传输,将预计算嵌入支持扩展到另外五个向量存储,为新的 MCP 协议修订版带来服务器端支持,并升级到 Anthropic Java SDK 3.x。
本版本新增内容
决策模型
应用中的许多决策只有少量已知可能结果:是或否、少数几个类别之一,或某个量表上的等级。你可以询问聊天模型,但它会用自由文本回答,而你必须自己将这段文本转换为可靠的结果。新的 DecisionModel API 正是为这些决策而设计。你描述可能的结果,模型会选择其中一个,并告诉你每个结果的可能性,而不是生成文本。
它遵循其他模型 API 的形态:输入 DecisionPrompt,输出 DecisionResponse,并用 DecisionOptions 调整调用。一个提示词包含一个输入(一段文本、一组命名字段或一段对话)以及一个或多个命名问题:
YesNoQuestion,以“是”的概率作答。ChoiceQuestion,以选定选项作答,并在提供方报告时给出每个选项的概率。ScoreQuestion,以有序量表中的一个等级作答,例如unhappy、neutral、happy。
由于答案携带概率,你的应用可以决定模型在采取行动前必须有多确定。决策模型仍然是机器学习模型,而不是规则引擎,因此其答案并非确定性的;参考文档说明了如何考虑阈值和错误答案。典型用途包括分类、护栏(例如在提示词注入到达聊天模型之前将其阻止)以及日常业务逻辑。
提供三种实现:
- OpenAI:OpenAiDecisionModel,由 OpenAI Decisions API 支持,并由 OpenAI starter 在
spring.ai.openai.decision下自动配置。 - Ollama:OllamaDecisionModel,由 Ollama starter 自动配置。它默认使用
d1-omni:600m,并可通过spring.ai.ollama.init.pull-model-strategy=when_missing在启动时拉取模型。这是试用该 API 最快的方式,因为它在你自己的机器上运行且无需 API 密钥。 - System One:SystemOneDecisionModel,基于 TypeSafe Java SDK 构建。一个模型即可服务所有使用 System One 协议的服务器,例如 TypeSafe Jev、Laya 和 Ollama。它不会自动配置:你需要从
TypeSafeClient创建它。
决策模型调用以 decision 操作名进行观测,新的 spring-ai-autoconfigure-model-decision-observation 模块新增了 token 使用量指标。
其他 Spring AI 功能已经基于新 API 构建:
- RAG 后处理器。
DecisionDocumentReranker通过询问每篇文档是否回答查询来重新排序检索到的文档,DecisionDocumentFilter则在文档进入提示词之前筛查提示词注入、矛盾和相关性问题。两者都会将针对每篇文档的调用分发到执行器,并可在虚拟线程上运行。它们采用 fail-open 策略,保留模型无法判断的文档并记录数量;过滤器则可改为 fail-closed。 - 工具搜索。
DecisionToolIndex是继正则、Lucene 和向量索引之后的第四种ToolIndex策略。它向决策模型询问哪个已索引工具最适合该请求,并在同一次调用中询问是否有任何工具适用,因此它可以报告没有工具适用,而不是返回最接近的错误工具。在工具搜索 Advisor 中通过spring.ai.chat.client.tool-search-advisor.tool-index-type=decision启用,并通过同一前缀下的decision.applicability-threshold和decision.minimum-relevance属性进行调整。
工具调用参数流式传输
模型会逐段流式输出工具调用的参数,而此前 Spring AI 只暴露完整调用。Anthropic、OpenAI(Chat Completions 和 Responses)、Amazon Bedrock Converse 和 DeepSeek 的工具调用参数增量现在会以标记为 partial 的 ToolCallPart 流式输出,因此 UI 可以在模型仍在生成工具调用时显示它。完整调用仍会随后出现,索引相同。
部分 ToolCallPart 不是工具调用:getToolCalls() 和 hasToolCalls() 会跳过它,ToolCallingManager 和 ToolCallingAdvisor 会忽略它,请求转换器不会将其发送回提供方。MessageAggregator 也会跳过部分片段,因此工具调用循环之外的 Advisor(例如聊天记忆)能看到增量,但绝不会持久化没有结果的工具调用;并且,在工具调用中途停止的流不再聚合为参数被截断的调用。
在更多向量存储中使用自己的嵌入
M1 新增了 VectorStore.upsert(),用于写入你自己计算的向量;RC1 新增了 similaritySearch(float[], SearchRequest),用于使用自己的查询向量进行搜索,最初面向 pgvector、Qdrant、Redis、Elasticsearch 和 OpenSearch。现在以下存储也实现了这两项功能:
- Neo4j
- MongoDB Atlas
- Typesense
- MariaDB
- Chroma
请参阅参考文档中的使用用户提供的查询嵌入进行搜索。
MCP 2026-07-28(“现代”)服务器
Spring AI MCP 服务器现在可以与现有的 STDIO、SSE、STREAMABLE 和 STATELESS 服务器并列,支持 Model Context Protocol 的 2026-07-28 修订版。通过 spring.ai.mcp.server.protocol=MODERN 激活它。
该修订版移除了 initialize 和会话。server/discover 是可缓存的请求,每个请求都携带协议版本和客户端能力,服务器发起的输入(例如 elicitation、sampling 和 roots)变为多轮往返请求,变更通知通过 subscriptions/listen 传递。该集成基于 MCP Java SDK 2.2(当前为 2.2.0-M2)的现代 API 构建,并带来:
- 通过单个 POST 端点提供该修订版的 WebMVC 和 WebFlux 传输,支持服务器发送事件流,并支持 STDIO。
- 用于工具、提示词、资源和补全的内存存储库,支持运行时
add和remove、变更广播以及分页。 - 为
@McpTool、@McpResource、@McpPrompt和@McpComplete提供现代方法回调。方法可声明McpModernSyncRequestContext以读取请求数据和多轮往返字段,并可声明McpSyncNotifier以报告进度。 - 三个注解上的
requiredCapabilities,用于列出方法无法缺少的客户端能力。服务器会在方法运行前返回错误。 - 新的定义属性:
@McpIcon、@McpArg(title)、@McpResource(size, ttlMs, cacheScope)和@McpToolParam(header = true)。 spring.ai.mcp.server.modern.*下的新属性。
STATELESS 服务器的注解式工具、资源和提示词只需更改属性即可迁移。对于 STREAMABLE 服务器,绑定会话的 ctx.elicit 和 ctx.sample 调用会变为上述多轮往返请求,ctx.progress 变为 McpSyncNotifier。客户端日志记录、ctx.roots() 和 ctx.ping() 在现代上下文中尚无对应项。两种迁移的可用示例都在 spring-ai-examples 中。目前仅支持同步 API 类型,type=ASYNC 与 protocol=MODERN 组合会在启动时失败。请参阅现代服务器参考页面。
其他新增
SessionService通过appendEvents(sessionId, events, expectedVersion)和getEventVersion(sessionId)暴露带版本检查的追加操作。从日志派生事件的代码现在可以在并发场景下安全写入它们,并且系统消息检查适用于批次中的每个事件。- Anthropic Java SDK 从 2.72.0 升级到 3.4.0(请参阅下方升级说明)。
升级说明
有一些变更可能需要你在代码中做出调整。Anthropic 和工具调用流式传输变更的详细信息见升级说明:
- Anthropic Java SDK 3.x 默认使用 API 版本
2026-10-21,该版本会拒绝temperature、topP和topK,即使将它们设置为默认值也是如此。Spring AI 保留采样方法和 Boot 属性,但将其标记为已弃用。作为模型默认值或请求覆盖设置的值会被丢弃且绝不会发送,并会通过 WARN 消息列出,因此请从配置中移除它们。扩展思考不再需要temperature(1.0)。Anthropic 迁移指南涵盖了这些细节。 - Anthropic API 密钥现在以
Authorization: Bearer发送,而不是X-Api-Key。 spring.ai.vectorstore.typesense.embedding-dimension不再默认值为1536。只有在设置时才传递给存储,因此向量大小来自现有集合的 schema;对于新集合,则来自嵌入模型。- 当读取集合因“未找到”以外的任何原因失败时,
TypesenseVectorStore会使初始化失败。此前,启动会继续。 - Anthropic 和 Bedrock Converse 的提示词 token 现在包含从提示词缓存读取和写入的 token(见下方修复),因此对于使用提示词缓存的请求,它们以及
gen_ai.usage.input_tokens观测属性会报告更高的值。对于 Anthropic,Usage.getTotalTokens()也包含缓存 token。如果你的应用手动将缓存 token 加到提示词 token 上来补偿,请移除该调整,否则它们会被重复计算。 - 仅以部分片段流式输出工具调用的自定义
ChatModel,现在还必须发出完整的ToolCallPart,且索引相同。 DeepSeekChatModel通过新的DeepSeekApi.chatCompletionStreamRaw进行流式传输。覆盖chatCompletionStream的DeepSeekApi子类不再被它调用,而仅打桩chatCompletionStream的测试 mock 会使流式传输因NullPointerException失败。请改为覆盖或打桩chatCompletionStreamRaw。
修复
- Anthropic 和 Bedrock Converse:提示词 token 以及由其派生的
gen_ai.usage.input_tokens观测属性此前低估了缓存请求的输入,因为提供方的输入 token 不包含缓存读取和缓存写入 token。现在它们在调用和流式路径中都是三者之和。对于 Anthropic 流式传输,当后续增量省略message_start的缓存用量时,会保留该用量。 - MCP:与另一个工具冲突的工具会保留其解析后的名称。在
tools/list_changed刷新之后,两个暴露同一工具的连接可能获得相同名称,回调提供方会失败并报出“Multiple tools with the same name”。 - Typesense:当
topK大于 10 时,搜索最多只返回 10 个文档;自动配置的存储从未从集合 schema 读取向量大小。当 Typesense 返回的导入结果少于发送的文档数时(例如某个文档无法序列化为 JSON),新的upsert也会失败,而不是报告成功。
依赖与构建
- Spring Boot 4.2.0-RC2
- MCP Java SDK 2.2.0-M2
- Anthropic Java SDK 3.4.0
- TypeSafe Java SDK 0.4.0
贡献者
感谢所有参与此版本工作的人:
@Ajax-1、@iuliiasobolevska、@sobychacko、@ThomasVitale、@tzolov 和 @dimitarproynov
后续计划
接下来是 2.1.0 GA。在此之前,我们将重点收集对上述功能的反馈。
开始使用
在现有应用中试用该候选版本,或在 start.spring.io 上新建应用。DecisionModel 和新的 MCP“现代”服务器都是新 API,我们希望在 GA 之前了解它们如何契合你的用例——如果发现问题,请提交 issue;如果想告诉我们接下来希望看到什么,请发起讨论。