聊天模型
约 30245 字大约 101 分钟
2026-09-15
合集说明
本篇合并自参考文档「Models / Chat Models」章节,覆盖总览、模型对比与 15 家聊天模型提供商,按官方文档顺序排列:(各篇之间以 --- 分隔)
- Chat Models(聊天模型)
- Chat Models Comparison(聊天模型对比)
- Amazon Bedrock Converse(Amazon Bedrock 对话 API)
- Anthropic Claude(Anthropic Claude 聊天)
- Azure OpenAI(Azure OpenAI 聊天)
- DeepSeek(DeepSeek 聊天)
- Docker Model Runner(Docker Model Runner 聊天)
- Google GenAI(Google GenAI 聊天)
- Groq Chat
- Mistral AI Chat
- MiniMax Chat
- NVIDIA Chat
- Ollama Chat
- Perplexity Chat
- OCI Generative AI Chat
- OpenAI Chat(上篇:基础与高级能力)
- OpenAI Chat(下篇:高级特性)
Chat Models(聊天模型)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chatmodel.html 📌 原文版本:Java AI 2.0.1
CHAT MODEL API(聊天模型 API)
Chat Model API(聊天模型 API)能让开发者在自己的应用里集成 AI 驱动的聊天补全(chat completion)能力。它使用了预训练语言模型,比如 GPT(Generative Pre-trained Transformer,生成式预训练 Transformer),根据用户的自然语言输入生成类似人类的回复。
这个 API 通常的工作方式是:先把一个 prompt(提示)或者部分对话发给 AI 模型,模型根据自己的训练数据和对自然语言模式的理解,生成一段补全或者对话的延续。生成的回复再返回给应用,应用可以展示给用户或者做进一步处理。
Java AI 的 Chat Model API 被设计成一个简单、可移植(portable)的接口,用来和各种不同的 AI 模型交互,让开发者可以用最少的代码改动在不同模型之间切换。这种设计符合 Spring 一贯的模块化(modularity)和可替换(interchangeability)理念。
另外,借助 Prompt(输入封装)和 ChatResponse(输出处理)这类伴生类(companion class),Chat Model API 统一了和 AI 模型的通信方式。它把请求准备和响应解析的复杂度都管理起来了,对外提供一个直接、简化的 API 交互方式。
你可以在 Available Implementations(可用实现)一节看到所有可用实现,在 Chat Models Comparison(聊天模型对比)一节看到详细的对比。
API OVERVIEW(API 概览)
这一节介绍 Java AI Chat Model API 的接口和相关类。
CHATMODEL
下面是 ChatModel 接口的定义:
public interface ChatModel extends Model<Prompt, ChatResponse>, StreamingChatModel {
// 简化版:直接传一个字符串消息,返回字符串回复
default String call(String message) {...}
@Override
ChatResponse call(Prompt prompt);
}带 String 参数的 call() 方法简化了初次使用,避免了一上来就接触更复杂的 Prompt 和 ChatResponse 类。但在真实应用里,更常见的做法是使用接受 Prompt 实例、返回 ChatResponse 的 call() 方法。
白话解读
简单说,ChatModel 是"发一条消息、拿一条回复"的门面(facade)。你可以偷懒直接 call("你好"),也可以正经点,把消息、参数都封装进 Prompt 再调用,后一种更灵活。
STREAMINGCHATMODEL
下面是 StreamingChatModel 接口的定义:
public interface StreamingChatModel extends StreamingModel<Prompt, ChatResponse> {
// 简化版:直接传一个字符串消息,返回一个字符串流
default Flux<String> stream(String message) {...}
@Override
Flux<ChatResponse> stream(Prompt prompt);
}stream() 方法的入参和 ChatModel 类似,可以传 String 或 Prompt,区别在于它用响应式(reactive)的 Flux API 把响应以流式(streaming)方式一点点吐出来。
白话解读
call 是"等模型把话说完再一次性返回",stream 是"模型边说边返回"。做聊天机器人那种打字机效果,就用 stream。
PROMPT
Prompt 是一个 ModelRequest(模型请求),它封装了一组 Message 对象,以及可选的模型请求参数。下面展示了 Prompt 类的简化版本,省略了构造器和其他工具方法:
public class Prompt implements ModelRequest<List<Message>> {
// 消息列表(对话内容)
private final List<Message> messages;
// 可选的模型参数
private ChatOptions modelOptions;
@Override
public ChatOptions getOptions() {...}
@Override
public List<Message> getInstructions() {...}
// 构造器和工具方法已省略
}MESSAGE
Message 接口封装了 Prompt 的文字内容、一组元数据(metadata)属性,以及一个叫做 MessageType(消息类型)的分类。
接口定义如下:
public interface Content {
// 文字内容
String getText();
// 元数据
Map<String, Object> getMetadata();
}
public interface Message extends Content {
// 消息类型(即角色)
MessageType getMessageType();
}多模态(multimodal)消息类型还额外实现了 MediaContent 接口,提供一组 Media(媒体)内容对象:
public interface MediaContent extends Content {
// 多媒体内容集合(如图片、音频)
Collection<Media> getMedia();
}Message 接口有多个实现,分别对应 AI 模型能处理的不同消息类别。
聊天补全端点(chat completion endpoint)会根据对话角色(conversational role)来区分消息类别,这在代码里就由 MessageType 映射。
比如 OpenAI 就区分 system(系统)、user(用户)、function(函数)、assistant(助手)这些对话角色。
提示
虽然 MessageType 这个名字听起来像是指某个消息格式,但在这个语境下,它实际表示的是消息在对话里扮演的角色(role)。
对于不使用特定角色的 AI 模型,UserMessage 实现就充当标准类别,通常代表用户提出的问题或指令。想了解 Prompt 和 Message 的实际用法以及它们和这些角色/类别的对应关系,请看 Prompts 一节的详细说明。
CHAT OPTIONS(聊天参数)
ChatOptions 表示可以传给 AI 模型的参数。它是 ModelOptions 的子类,用来定义一些可移植的、能传给 AI 模型的选项。ChatOptions 类定义如下:
public interface ChatOptions extends ModelOptions {
// 模型名称
String getModel();
// 频率惩罚
Double getFrequencyPenalty();
// 最大 token 数
Integer getMaxTokens();
// 存在惩罚
Double getPresencePenalty();
// 停止序列
List<String> getStopSequences();
// 温度(随机性)
Double getTemperature();
// Top-K 采样
Integer getTopK();
// Top-P 采样
Double getTopP();
ChatOptions.Builder<?> mutate();
}此外,每个模型特定的 ChatModel / StreamingChatModel 实现都可以有自己的参数,也能传给 AI 模型。比如 OpenAI 的 Chat Completion 模型就有 logitBias、seed、user 这样的自有参数。
Java AI 提供了一套很讲究的机制来配置和使用 Chat Models。你可以在启动时设置默认配置(default configuration),同时也能按请求(per-request)灵活地覆盖这些设置。这样开发者既能轻松对接不同 AI 模型、按需调整参数,又能都统一在 Java AI 框架提供的一致接口里。
当你用 ChatModel.call() / ChatModel/stream() 时,传入的 prompt 需要包含一套完整的选项,它会完全覆盖模型里设置的选项(或者把 Prompt 的 options 设为 null 来使用模型的默认值)。
而 ChatClient 抽象允许一种渐进式的做法:用户可以提供一个"增量(delta)"自定义器(customizer),按请求逐个覆盖默认选项。
下面的流程图展示了 Java AI 是如何处理 Chat Models 的配置和执行的:

启动时配置(Start-up Configuration)——
ChatModel/StreamingChatModel在初始化时会带上"启动时"的 Chat Options。这些选项在初始化时设置,用来提供默认配置。运行时配置(Runtime Configuration)——每次请求时,
Prompt可以带上运行时 Chat Options,这些选项会完全覆盖启动时选项。输入处理(Input Processing)——"Convert Input(转换输入)"这一步把输入指令转换成模型原生的、模型特定的格式。
输出处理(Output Processing)——"Convert Output(转换输出)"这一步把模型的响应转换成标准化的
ChatResponse格式。
CHATRESPONSE
ChatResponse 类的结构如下:
public class ChatResponse implements ModelResponse<Generation> {
// 响应元数据
private final ChatResponseMetadata chatResponseMetadata;
// 生成结果列表
private final List<Generation> generations;
@Override
public ChatResponseMetadata getMetadata() {...}
@Override
public List<Generation> getResults() {...}
// 其他方法已省略
}ChatResponse 持有 AI 模型的输出,其中每个 Generation(生成结果)实例包含一个可能的结果——一次 prompt 可能产生多个结果。
ChatResponse 还带有 ChatResponseMetadata,即关于 AI 模型响应的元数据。
GENERATION
最后,Generation 类继承自 ModelResult,代表模型输出(即 assistant message 助手消息)及相关元数据:
public class Generation implements ModelResult<AssistantMessage> {
// 助手消息
private final AssistantMessage assistantMessage;
// 生成结果元数据
private ChatGenerationMetadata chatGenerationMetadata;
@Override
public AssistantMessage getOutput() {...}
@Override
public ChatGenerationMetadata getMetadata() {...}
// 其他方法已省略
}AVAILABLE IMPLEMENTATIONS(可用实现)
下图展示了统一的接口 ChatModel 和 StreamingChatModel,它们被用来和来自不同厂商的各种 AI 聊天模型交互。这样既能轻松集成和切换不同的 AI 服务,又能给客户端应用保持一致(consistent)的 API。

- OpenAI Chat Completion(支持流式、多模态以及 function-calling 函数调用)
- Ollama Chat Completion(支持流式、多模态以及 function-calling 函数调用)
- Amazon Bedrock
- Mistral AI Chat Completion(支持流式以及 function-calling 函数调用)
- Anthropic Chat Completion(支持流式以及 function-calling 函数调用)
关于各个可用 Chat Models 的详细对比,请见 Chat Models Comparison 一节。
CHAT MODEL API(聊天模型 API)
Java AI 的 Chat Model API 构建在 Java AI Generic Model API(通用模型 API)之上,提供了聊天专用的抽象和实现。这样一来,就很容易在集成和切换不同 AI 服务的同时,给客户端应用保持一致的 API。下面的类图展示了 Java AI Chat Model API 的主要类和接口。

白话解读
整个页面其实讲的就是 Java AI 给聊天模型做的"插座标准"。不管底下插的是 OpenAI、Anthropic 还是别家,你写代码时只需要面对 ChatModel / StreamingChatModel 两个接口,输入用 Prompt(里面装着一串 Message,每条消息带个角色),输出拿到 ChatResponse(里面装着若干 Generation)。想换厂商,改配置就行,业务代码基本不用动。
Chat Models Comparison(聊天模型对比)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/comparison.html 📌 原文版本:Java AI 2.0.1
概述(简介)
本页提供了一张对比表格,用来比较 Java AI 支持的各个 Chat Models(聊天模型)各自具备哪些能力。表格里列的对比维度(capabilities)含义如下:
- Multimodality(多模态):模型能处理的输入类型有哪些(比如 text 文本、image 图片、audio 音频、video 视频)。
- Tools/Function Calling(工具/函数调用):模型是否支持 function calling(函数调用)或 tool use(工具使用)。
- Streaming(流式输出):模型是否支持 streaming responses(流式响应)。
- Retry(重试):是否支持 retry mechanisms(重试机制)。
- Observability(可观测性):是否具备 monitoring and debugging(监控与调试)相关功能。
- Built-in JSON(内置 JSON):是否原生支持 JSON output(JSON 输出)。
- Local deployment(本地部署):模型能否在本地运行。
- OpenAI API Compatibility(OpenAI API 兼容性):模型是否兼容 OpenAI 的 API。
白话解读
这张表其实就是一张"选型对照表"。你在用 Java AI 接一个大模型之前,先看看这个模型支不支持你要的功能——比如你想让它看图(多模态)、想让它调用你写的 Java 方法(Function Calling)、想边生成边输出(Streaming),都能在表里一眼查到。注意原文表格里很多单元格是空的,说明该功能在文档中没有标注或不被支持。
对比维度表格(Multimodality / Tools / Streaming / Retry / Observability / Built-in JSON / Local / OpenAI API Compatible)
| Provider(提供方) | Multimodality(多模态输入类型) | Tools/Functions(工具/函数调用) | Streaming(流式输出) | Retry(重试) | Observability(可观测性) | Built-in JSON(内置 JSON) | Local(本地部署) | OpenAI API Compatible(兼容 OpenAI API) |
|---|---|---|---|---|---|---|---|---|
| Anthropic Claude | text, pdf, image(文本、PDF、图片) | |||||||
| DeepSeek (OpenAI-proxy)(DeepSeek,通过 OpenAI 代理) | text(文本) | |||||||
| Google GenAI | text, pdf, image, audio, video(文本、PDF、图片、音频、视频) | |||||||
| Groq (OpenAI-proxy)(Groq,通过 OpenAI 代理) | text, image(文本、图片) | |||||||
| Mistral AI | text, image, audio(文本、图片、音频) | |||||||
| MiniMax (Anthropic-proxy)(MiniMax,通过 Anthropic 代理) | text, image(文本、图片) | |||||||
| NVIDIA (OpenAI-proxy)(NVIDIA,通过 OpenAI 代理) | text, image(文本、图片) | |||||||
| Ollama | text, image(文本、图片) | |||||||
| OpenAI | In: text, image, audio Out: text, audio(输入:文本、图片、音频;输出:文本、音频) | |||||||
| Perplexity (OpenAI-proxy)(Perplexity,通过 OpenAI 代理) | text(文本) | |||||||
| Amazon Bedrock Converse | text, image, video, docs (pdf, html, md, docx … )(文本、图片、视频、文档,如 PDF、HTML、Markdown、DOCX 等) |
关于表格中空白单元格的说明
原文页面的对比表格中,除 Multimodality(多模态)这一列之外,其余列(Tools/Functions、Streaming、Retry、Observability、Built-in JSON、Local、OpenAI API Compatible)在抓取到的内容里均为空白,页面未提供对应的勾选标记或文字说明。因此上方表格忠实保留了这些空白,未做推测性填充。
白话解读
补充一点模型选择的直觉:Ollama 那一行是唯一明显能"Local(本地部署)"跑的,因为 Ollama 本身就是本地推理工具;带 "(OpenAI-proxy)" 的几家其实不是自己独有的接口,而是借道 OpenAI 的 API 规范来接入,选它们时配置方式会和直接用 OpenAI 很像。多模态最强的看起来是 Google GenAI 和 Amazon Bedrock Converse,一个是"文本+PDF+图+音+视频"全都要,一个是覆盖文档格式最广。
版本与页脚信息
- 文档所属:Java AI
- 版本状态:Stable(稳定版) 2.0.1、1.1.8、1.0.9;Snapshot(快照版) 2.0.2-SNAPSHOT、1.1.9-SNAPSHOT
- 版权:Copyright © 2005 - Broadcom. All Rights Reserved.
关于页面发布/作者信息:本次抓取到的原文内容中,未包含明确的发布作者、发布机构署名或具体的发布日期/时间戳;仅能确认版权标记为 "Copyright © 2005 - Broadcom" 及文档版本为 Java AI 2.0.1。来源站点为 docs.spring.io(Spring 官方文档)。
Amazon Bedrock Converse(Amazon Bedrock 对话 API)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/bedrock-converse.html 📌 原文版本:Java AI 2.0.1
Bedrock Converse API 概览(Amazon Bedrock 对话 API 总览)
Amazon Bedrock Converse API 提供了一个统一的接口(interface)来访问各种对话式 AI 模型(conversational AI models,即可以聊天的 AI),并具备以下增强能力:函数/工具调用(function/tool calling)、多模态输入(multimodal inputs,即同时处理文字和图片)、流式响应(streaming responses,即一个字一个字地返回结果而不是等全部生成完)。
Bedrock Converse API 的主要特性:
- Tool/Function Calling(工具/函数调用): 在对话过程中支持定义函数并让模型调用
- Multimodal Input(多模态输入): 能在对话中同时处理文字和图片
- Streaming Support(流式支持): 实时地把模型响应流式输出
- System Messages(系统消息): 支持系统级的指令和上下文设置
白话解读
打个比方,Converse API 就像一个"万能遥控器"——以前每种 AI 模型(Claude、Nova、Llama 等)都有自己的一套操作方式,现在 AWS 给你做了个统一遥控器,按一个键就能控制所有电视,省得你来回换遥控器。
Bedrock Converse API 在多个模型厂商之间提供了统一接口,同时帮你处理 AWS 特有的认证(authentication)和基础设施(infrastructure)问题。目前 Converse API 支持的模型包括:Amazon Titan、Amazon Nova、AI21 Labs、Anthropic Claude、Cohere Command、Meta Llama、Mistral AI。
按照 Bedrock 的建议,Java AI 正在把所有聊天对话实现迁移到 Amazon Bedrock 的 Converse API。虽然现有的 InvokeModel API 也支持对话应用,但我们强烈建议所有对话模型都采用 Converse API。
Converse API 不支持 embedding(嵌入,即把文字转成数字向量)操作,所以这部分仍保留在原 API 中,现有 InvokeModel API 中的 embedding 模型功能将继续维护。
Prerequisites(前置要求)
参考 Getting started with Amazon Bedrock 来设置 API 访问。
获取 AWS 凭证: 如果你还没有 AWS 账号和配置 AWS CLI(命令行工具),可以看这个视频教程。你应该能拿到你的 access key(访问密钥)和 secret key(密钥)。
启用要用的模型: 打开 Amazon Bedrock 控制台,从左侧的 Model Access 菜单配置你要用的模型的访问权限。
信息
简单说:你需要先在 AWS 后台"开门"(启用模型),再给 Java AI 一把"钥匙"(AWS 凭证),才能用起来。
Auto-Configuration(自动配置)
Java AI 自动配置和 starter 模块的 artifact 名称有了重大变化。请参考 upgrade notes(升级说明)了解更多信息。
在你的项目的 pom.xml (Maven) 或 build.gradle (Gradle) 中加上 spring-ai-starter-model-bedrock-converse 依赖:
Maven(Java 项目常用的构建工具):
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-bedrock-converse</artifactId>
</dependency>Gradle(另一种构建工具):
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-bedrock-converse'
}参考 Dependency Management(小节)把 Java AI BOM(BOM = Bill of Materials,物料清单,统一管理依赖版本)加到你的构建文件里。
Chat Properties(聊天属性配置)
spring.ai.bedrock.aws 是配置 AWS Bedrock 连接的前缀。
| 属性(Property) | 说明 | 默认值 |
|---|---|---|
spring.ai.bedrock.aws.region | 要使用的 AWS 区域(region,即服务器所在地理位置) | us-east-1(美国东部,弗吉尼亚) |
spring.ai.bedrock.aws.timeout | 整个 API 调用的最大时长 | 5m(5 分钟) |
spring.ai.bedrock.aws.connection-timeout | 建立连接的最大等待时长 | 5s(5 秒) |
spring.ai.bedrock.aws.connection-acquisition-timeout | 从连接池等待新连接的最大时长 | 30s(30 秒) |
spring.ai.bedrock.aws.async-read-timeout | 读取异步响应的最大时长 | 30s(30 秒) |
spring.ai.bedrock.aws.access-key | AWS access key(访问密钥 ID) | - |
spring.ai.bedrock.aws.secret-key | AWS secret key(秘密访问密钥) | - |
spring.ai.bedrock.aws.session-token | 临时凭证的 session token(会话令牌) | - |
spring.ai.bedrock.aws.profile.name | AWS profile(配置文件)名称 | - |
spring.ai.bedrock.aws.profile.credentials-path | AWS credentials 文件路径 | - |
spring.ai.bedrock.aws.profile.configuration-path | AWS config 文件路径 | - |
聊天自动配置的启用和禁用现在通过顶级前缀 spring.ai.model.chat 来配置:
- 启用:
spring.ai.model.chat=bedrock-converse(默认就是启用) - 禁用:
spring.ai.model.chat=none(或任何不匹配bedrock-converse的值)
这个变更是为了支持同时配置多个模型。
spring.ai.bedrock.converse.chat 是配置 Converse API 聊天模型实现的前缀。
| 属性 | 说明 | 默认值 |
|---|---|---|
spring.ai.model.chat | 启用 Bedrock Converse 聊天模型 | bedrock-converse |
spring.ai.bedrock.converse.chat.model | 要使用的模型 ID | 没有默认值,需要从 AWS Bedrock 控制台选择 |
spring.ai.bedrock.converse.chat.temperature | 控制输出的随机性。取值范围 [0.0, 1.0],越大越发散 | 0.8 |
spring.ai.bedrock.converse.chat.top-p | 采样时考虑的 token(词元,模型处理文字的最小单位)累积概率最大值 | AWS Bedrock 默认 |
spring.ai.bedrock.converse.chat.top-k | 生成下一个 token 时考虑的候选数量 | AWS Bedrock 默认 |
spring.ai.bedrock.converse.chat.max-tokens | 生成响应中最多包含多少个 token | 500 |
选区域小贴士
你需要在 AWS 控制台开通模型访问的那个 region 才能用对应模型。比如 Claude 某些版本只在 us-east-1、us-west-2、eu-central-1 等地区可用。选择离你用户最近的 region 一般网络延迟更低、成本可能更便宜。
Runtime Options(运行时选项)
使用可移植的 ChatOptions 或 BedrockChatOptions builder(构建器)来创建模型配置,比如 temperature(温度)、maxToken(最大 token)、topP 等。
启动时,可以通过 BedrockConverseProxyChatModel(api, options) 构造函数或 spring.ai.bedrock.converse.chat.* 属性配置默认选项。
运行时,你可以通过给 Prompt 调用添加新的、请求级别的选项来覆盖默认选项:
// 构建自定义聊天选项:指定模型、温度、最大 token,并注册一个查天气工具
var options = BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0") // 指定用 Claude Haiku 4.5 模型
.temperature(0.6) // 降低随机性,回答更稳定
.maxTokens(300) // 限制回答长度
.toolCallbacks(List.of(FunctionToolCallback.builder("getCurrentWeather", new WeatherService()) // 注册一个名为 getCurrentWeather 的工具
.description("Get the weather in location. Return temperature in 36°F or 36°C format. Use multi-turn if needed.") // 工具描述,告诉 AI 这个工具干啥
.inputType(WeatherService.Request.class) // 参数类型
.build()))
.build();
// 用 ChatClient 发起调用,把上面配置塞进去
String response = ChatClient.create(this.chatModel)
.prompt("What is current weather in Amsterdam?") // 问阿姆斯特丹天气
.options(options) // 使用自定义选项
.call() // 同步调用(等结果回来)
.content(); // 取文字内容白话解读
Runtime Options 就是"临时改设置"。比如你默认想让 AI 自由发挥(temperature=0.8),但这次希望它严肃点查天气,就临时把温度调到 0.6,给它装一个"查天气"的工具,这样它就会自己调用工具拿到实时数据再回答你。
Prompt Caching(提示缓存)
AWS Bedrock 的 prompt caching(提示缓存)功能让你能把常用的 prompt 缓存起来,减少成本并改善重复交互的响应时间。当你缓存了一个 prompt 后,后续相同的请求可以直接复用缓存内容,显著减少需要处理的输入 token 数量。
信息
缓存就像你背课文——第一次背要花时间(cache write,要多付 25% 的钱),但第二次背就快了(cache read,只要付原价的 10%)。所以多问几次相同内容的问题就很划算。
Supported Models(支持的模型)
Prompt caching 在通过 AWS Bedrock 提供的 Claude 3.x、Claude 4.x 以及 Amazon Nova 模型上可用。
Token Requirements(Token 数量要求)
不同模型的缓存生效最低 token 阈值不同:
- Claude Sonnet 4 及大多数模型:1024+ 个 token
- 不同模型有不同要求——请查阅 AWS Bedrock 文档
Cache Strategies(缓存策略)
Java AI 通过 BedrockCacheStrategy 枚举提供策略化的缓存位置选择:
- NONE(无): 完全禁用 prompt caching(默认)
- SYSTEM_ONLY(仅系统消息): 只缓存系统消息内容
- TOOLS_ONLY(仅工具): 只缓存工具定义(仅 Claude 模型支持)
- SYSTEM_AND_TOOLS(系统+工具): 同时缓存系统消息和工具定义(仅 Claude 模型支持)
- CONVERSATION_HISTORY(对话历史): 在 chat memory(聊天记忆)场景下缓存整个对话历史
白话解读
缓存点位(cache breakpoint)就像书签。AWS 规定一本书最多只能放 4 个书签。Java AI 帮你智能选择书签放哪里——是要标记"开头说明"(SYSTEM_ONLY),还是"附录工具表"(TOOLS_ONLY),还是两个都标记。
这种策略化方式在遵守 AWS Bedrock 4 个缓存点位限制的同时,保证了缓存断点位置最优。
Amazon Nova Limitations(Amazon Nova 的限制)
Amazon Nova 模型(Nova Micro、Lite、Pro、Premier)只支持缓存 system 和 messages 内容,不支持缓存 tools。
如果你对 Nova 模型使用 TOOLS_ONLY 或 SYSTEM_AND_TOOLS 策略,AWS 会返回 ValidationException。对 Amazon Nova 模型请使用 SYSTEM_ONLY 策略。
Enabling Prompt Caching(启用提示缓存)
通过在 BedrockChatOptions 上设置 cacheOptions 并选择策略来启用 prompt caching。
SYSTEM-ONLY Caching(仅缓存系统消息)
最常见的场景——在多个请求间缓存系统指令:
// 只缓存系统消息
ChatResponse response = chatModel.call(
new Prompt(
List.of(
// 系统消息放专家身份说明(很长所以值得缓存)
new SystemMessage("You are a helpful AI assistant with extensive knowledge..."),
new UserMessage("What is machine learning?") // 用户问机器学习是啥
),
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0") // Claude Haiku 模型
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_ONLY) // 选仅缓存系统消息策略
.build())
.maxTokens(500) // 限制输出长度
.build()
)
);TOOLS-ONLY Caching(仅缓存工具定义)
缓存大型工具定义,同时保持系统提示动态(仅 Claude 模型支持):
// 只缓存工具定义
ChatResponse response = chatModel.call(
new Prompt(
"What's the weather in San Francisco?", // 问旧金山天气
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.TOOLS_ONLY) // 策略:只缓存工具
.build())
.toolCallbacks(weatherToolCallbacks) // 大型工具定义,会被缓存
.maxTokens(500)
.build()
)
);警告
该策略仅支持 Claude 模型。Amazon Nova 模型会返回 ValidationException。
SYSTEM AND TOOLS Caching(同时缓存系统和工具)
同时缓存系统指令和工具定义以最大化复用(仅 Claude 模型支持):
// 同时缓存系统消息和工具定义
ChatResponse response = chatModel.call(
new Prompt(
List.of(
new SystemMessage("You are a weather analysis assistant..."), // 系统消息
new UserMessage("What's the weather like in Tokyo?") // 问东京天气
),
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_AND_TOOLS) // 策略:系统+工具都缓存
.build())
.toolCallbacks(weatherToolCallbacks) // 工具定义
.maxTokens(500)
.build()
)
);信息
此策略使用 2 个缓存断点(一个给工具,一个给系统)。仅 Claude 模型支持。
CONVERSATION HISTORY Caching(缓存对话历史)
为多轮对话场景缓存不断增长的对话历史:
// 配合 ChatClient 和 memory(记忆)使用,缓存对话历史
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultSystem("You are a personalized career counselor...") // 默认系统提示
.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()) // 挂载一个记忆 advisor(advisor 是 Spring AI 的拦截器概念)
.build();
String response = chatClient.prompt()
.user("What career advice would you give me?") // 用户问职业建议
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId)) // 传会话 ID 区分不同用户
.options(BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.CONVERSATION_HISTORY) // 策略:缓存整段对话
.build())
.maxTokens(500)
.build())
.call()
.content();MULTI-BLOCK SYSTEM MESSAGE CACHING(多块系统消息缓存)
当使用 advisor(例如 RAG 上下文注入)时,你的 system prompt 可能由多个 SystemMessage 实例组成:一个静态前缀(基础指令)和一个动态后缀(advisor 注入的、每次请求都变的上下文)。
默认情况下,当启用 SYSTEM_ONLY 或 SYSTEM_AND_TOOLS 缓存时,每个 SystemMessage 会被发成单独的 SystemContentBlock,缓存点放在最后一个 block 之后。如果那块内容在请求间有任何变化,整个 system 缓存都会失效——结果就是每次请求都要付 1.25 倍的 cache write 费用,而不是更便宜的 cache read。
multiBlockSystemCaching 选项通过把缓存点放在倒数第二个 system block 之后(即静态前缀和动态后缀之间的边界)来解决这个问题,这样即使最后一个 block 自由变化,静态部分依然保留在缓存里。
// 配置:多块系统消息缓存 + 1 小时 TTL(Time To Live,存活时间)
BedrockCacheOptions cacheOptions = BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_ONLY) // 仅缓存系统消息
.multiBlockSystemCaching(true) // 启用多块缓存,让静态部分继续被缓存
.ttl(BedrockCacheTtl.ONE_HOUR) // 缓存保留 1 小时
.build();
BedrockChatOptions chatOptions = BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(cacheOptions)
.build();
// 静态系统提示(会被缓存)
SystemMessage staticPrompt = new SystemMessage("You are an expert assistant...");
// 动态 RAG 上下文(advisor 注入,每次请求变化)
SystemMessage dynamicContext = new SystemMessage("Relevant context: " + ragResults);
Prompt prompt = new Prompt(List.of(staticPrompt, dynamicContext, new UserMessage("...")), chatOptions);白话解读
这相当于给"不变的前言"和"变的附录"中间夹了个书签。这样前言一直留在缓存里,附录随便换都不影响,省钱!
Cost Considerations(成本考量)
AWS Bedrock prompt caching 的价格(近似值,因模型而异):
- Cache write: 比基础 input token 贵约 25%
- Cache read: 比基础 input token 便宜约 90%(只付原价的 10%)
- 回本点(Break-even point): 经过 1 次 cache read,你就已经省钱了
白话解读
简单心法:只要同样的内容被问超过一次,缓存就划算。问得越多,省得越多。
Tool Calling(工具调用)
BedrockProxyChatModel 支持工具调用。模型可以请求工具执行,但不会自己跑工具——执行由 Java AI 处理。
对于大多数应用,使用 ChatClient 配合自动注册的 ToolCallingAdvisor——参考 Tool Calling。如果你想自己控制循环(比如把工具调用和 prompt caching 结合),可以参考 ChatModel Tool Calling。
// 工具回调定义示例:模型会自动触发该函数
FunctionToolCallback weatherTool = FunctionToolCallback.builder("getCurrentWeather", new WeatherService())
.description("Get the weather in location. Return temperature in 36°F or 36°C format. Use multi-turn if needed.")
.inputType(WeatherService.Request.class)
.build();Structured Output(结构化输出)
AWS Bedrock 通过 JSON Schema 支持原生结构化输出,保证模型生成的响应严格符合你指定的结构。该功能在支持的模型上可用,包括 Anthropic Claude 和 Amazon Nova。
Using ChatClient with Native Structured Output(用 ChatClient + 原生结构化输出)
使用结构化输出最简单的方式是 ChatClient 高级 API 配合 ENABLE_NATIVE_STRUCTURED_OUTPUT advisor:
// 定义目标数据结构:一个演员和他出演的电影列表
record ActorsFilms(String actor, List<String> movies) {}
// 通过 ChatClient 调用,让模型输出符合 ActorsFilms 结构的结果
ActorsFilms actorsFilms = ChatClient.create(chatModel).prompt()
.options(ToolCallingChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0") // 用 Claude Haiku
.build())
.advisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT) // 启用原生结构化输出 advisor
.user("Generate the filmography for a random actor.") // 让模型编一个演员的作品清单
.call()
.entity(ActorsFilms.class); // 直接拿回 Java 对象更多信息请参考 Structured Output 文档。
Multimodal(多模态)
多模态(Multimodality)指的是模型同时理解和处理多种来源信息的能力,包括文字、图片、视频、PDF、doc、html、md 等多种数据格式。
Bedrock Converse API 支持多模态输入,包括文字和图片输入,可以基于组合输入生成文字响应。
你需要一个支持多模态输入的模型,比如 Anthropic Claude 或 Amazon Nova 模型。
Images(图片)
对于支持视觉多模态的模型(比如 Amazon Nova、Anthropic Claude、Llama 3.2),Bedrock Converse API 允许你在 payload(请求载荷)中包含多张图片。
目前 Bedrock Converse 支持 base64(一种二进制编码方式,把图片转成文本字符串)编码的图片,支持的 MIME 类型(文件格式标识)包括 image/jpeg、image/png、image/gif、image/webp。
// 文本 + 图片组合输入
String response = ChatClient.create(chatModel)
.prompt()
.user(u -> u.text("Explain what do you see on this picture?") // 问 AI 看图说啥
.media(Media.Format.IMAGE_PNG, new ClassPathResource("/test.png"))) // 加载类路径下的 test.png
.call()
.content();Video(视频)
Amazon Nova 模型允许你在 payload 里包含单个视频,可以通过 base64 格式提供,也可以通过 Amazon S3 URI(S3 的资源链接)。
Documents(文档)
对于一些模型,Bedrock 允许你通过 Converse API 的文档支持在 payload 中包含文档,可以以字节形式提供。
Sample Controller(示例控制器)
新建一个 Spring Boot 项目,把 spring-ai-starter-model-bedrock-converse 加到你的依赖里。
在 src/main/resources 下加一个 application.properties 文件:
# AWS 连接配置
spring.ai.bedrock.aws.region=eu-central-1 # 区域:欧洲中部(法兰克福)
spring.ai.bedrock.aws.timeout=10m # API 调用最长 10 分钟
spring.ai.bedrock.aws.access-key=${AWS_ACCESS_KEY_ID} # 从环境变量读 access key
spring.ai.bedrock.aws.secret-key=${AWS_SECRET_ACCESS_KEY} # 从环境变量读 secret key
# 模型行为配置
spring.ai.bedrock.converse.chat.temperature=0.8 # 输出随机性
spring.ai.bedrock.converse.chat.top-k=15 # 候选 token 数下面是一个使用 chat model 的示例 controller(控制器,即 Web 接口层):
// 标记为 REST 控制器,对外暴露 HTTP 接口
@RestController
public class ChatController {
// Spring AI 的高级客户端,让调用更顺手
private final ChatClient chatClient;
// 通过构造器注入 ChatClient.Builder(构造器模式)
@Autowired
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder.build(); // 构建出 ChatClient 实例
}
// 同步接口:返回 AI 一次性生成的完整结果
@GetMapping("/ai/generate")
public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return Map.of("generation", this.chatClient.prompt(message).call().content());
}
// 流式接口:返回 Flux<ChatResponse>,一个字一个字地吐给前端
@GetMapping("/ai/generateStream")
public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return this.chatClient.prompt(message).stream().content();
}
}白话解读
两个接口的差别:/ai/generate 等所有字都生成完一次性返回;/ai/generateStream 像打字机一样一个字一个字推给前端,用户体验更流畅、感觉更快。
Chat Memory(聊天记忆)
Java AI 提供了通用的 ChatMemory 抽象来管理多轮对话上下文(具体实现可参考 Chat Memory 文档)。当与 Bedrock Converse 配合使用时,建议结合 MessageChatMemoryAdvisor 和 CONVERSATION_HISTORY 缓存策略一起使用,能在多轮对话中既快又省。
// 注入 ChatMemory bean
ChatMemory chatMemory = new InMemoryChatMemory();
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultSystem("You are a helpful assistant.")
.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
.build();
// 不同会话用不同 conversationId 区分
chatClient.prompt()
.user("My name is John.")
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, "user-001"))
.call()
.content();
chatClient.prompt()
.user("What is my name?")
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, "user-001"))
.call()
.content(); // 模型会记住是 JohnAnthropic Claude(Anthropic Claude 聊天)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/anthropic-chat.html 📌 原文版本:Java AI 2.0.1
Java AI 通过官方 Anthropic Java SDK(软件开发工具包)支持 Anthropic 的 Claude 模型(Claude 是 Anthropic 公司开发的一系列大语言模型),让你可以通过 Anthropic 的 API(应用程序编程接口,简单理解就是"调用 Claude 的网络入口")接入 Claude。
白话解读
简单说,这一章讲的就是:怎么在 Spring Boot 项目里调用 Claude 大模型。Anthropic 是公司名,Claude 是它家的大模型产品名。
Prerequisites(前置要求)
去 Anthropic Console 注册一个账号,然后在 API Keys 页面生成一个 API key(API 密钥,相当于你的"调用密码")。
Add Repositories and BOM(添加仓库和 BOM)
Java AI 的产物(artifact,编译后打成的 jar 包)发布在 Maven Central 和 Spring Snapshot 仓库。
为了方便依赖管理,Java AI 提供了一个 BOM(Bill of Materials,物料清单,本质就是一个"版本对齐"的 pom 文件),保证整个项目用的 Java AI 版本是一致的。
Auto-Configuration(自动配置)
通过 spring-ai-starter-model-anthropic 这个 starter(Spring Boot 启动器,"开箱即用依赖包")就能启用 Spring Boot 的自动配置。
Maven:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-anthropic</artifactId>
</dependency>Gradle:
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-anthropic'
}Configuration Properties(配置属性)
用 spring.ai.anthropic.* 这一组属性来配置 Anthropic 连接和聊天选项:
| 属性 | 描述 | 默认值 |
|---|---|---|
spring.ai.anthropic.api-key | Anthropic 的 API key(密钥) | - |
spring.ai.anthropic.base-url | API 的 base URL(基础访问地址) | api.anthropic.com |
spring.ai.anthropic.timeout | 启动时内置到共享 HTTP(超文本传输协议,就是浏览器和服务器之间对话的协议)客户端里的默认超时时间 | 60s |
spring.ai.anthropic.max-retries | 请求失败时的最大重试次数 | 2 |
spring.ai.anthropic.chat.model | 模型名字 | claude-haiku-4-5 |
spring.ai.anthropic.chat.max-tokens | 最大 token 数(token 是模型处理文字的最小单位) | 4096 |
spring.ai.anthropic.chat.temperature | 采样温度(数值越高回答越随机有创造性,越低越稳定死板) | - |
spring.ai.anthropic.chat.top-p | Top-p 采样(也叫核采样,从概率最高的若干 token 里挑,控制候选范围) | - |
spring.ai.anthropic.chat.top-k | Top-k 采样(只从概率最高的 k 个候选里选下一个 token) | - |
spring.ai.anthropic.chat.cache-options.strategy | 要使用的缓存策略 | NONE |
spring.ai.anthropic.chat.inference-geo | 请求处理所在的地理区域(us 或 eu,用于数据合规) | - |
spring.ai.anthropic.chat.service-tier | 容量路由:auto 或 standard_only | - |
Authentication(认证)
API key 既可以写在代码里,也可以通过环境变量配置。
// 用 builder 模式手动指定模型、最大 token 和从环境变量读取的 API key
var chatOptions = AnthropicChatOptions.builder()
.model("claude-sonnet-4-20250514")
.maxTokens(1024)
.apiKey(System.getenv("ANTHROPIC_API_KEY"))
.build();
var chatModel = AnthropicChatModel.builder()
.options(chatOptions)
.build();也可以设好环境变量,让 SDK 自动检测:
export ANTHROPIC_API_KEY=<your-api-key>Basic Usage(基础用法)
// 同步调用:直接拿到一次性完整响应
ChatResponse response = chatModel.call(
new Prompt("Generate the names of 5 famous pirates."));
// 流式调用:随着模型生成边推边返回,适合做打字机效果
Flux<ChatResponse> stream = chatModel.stream(
new Prompt("Generate the names of 5 famous pirates."));白话解读
call 是"等模型全部生成完一次性返回",stream 是"模型生成一个字就推一个字给你",做聊天界面的时候一般用 stream。
Runtime Options(运行时选项)
AnthropicChatOptions.java 这个类提供了模型相关的配置,比如用哪个模型、温度、最大 token 等等。
启动的时候,可以通过 AnthropicChatModel.builder().defaultOptions(options).build() 来设默认选项。
运行时,如果想覆盖默认值,可以在 Prompt 调用里带上新的、只针对这一次请求的选项:
// 这一次调用临时换成 claude-sonnet-4,并把温度调到 0.4
ChatResponse response = chatModel.call(
new Prompt(
"Generate the names of 5 famous pirates.",
AnthropicChatOptions.builder()
.model("claude-sonnet-4-20250514")
.temperature(0.4)
.build()
));Chat Options(聊天选项)
| 选项 | 描述 | 默认值 |
|---|---|---|
model | 要用的 Claude 模型名。可选:claude-sonnet-4-20250514、claude-opus-4-20250514、claude-3-5-sonnet-20241022 等 | claude-sonnet-4-20250514 |
maxTokens | 响应里最多生成多少个 token | 4096 |
temperature | 控制响应的随机性。范围:0.0-1.0 | 1.0 |
topP | 核采样参数(nucleus sampling)。只在 Claude Opus 4.6 及更早的模型上支持 | - |
topK | 每生成一个 token,只从概率最高的 K 个候选里挑。只在 Claude Opus 4.6 及更早模型支持 | - |
stopSequences | 自定义的"停止序列",模型遇到这些字符就停止生成 | - |
thinking | 思考配置(extended thinking 扩展思考) | - |
outputConfig | 结构化输出(JSON schema)以及 effort 控制 | - |
cacheOptions | 配置 prompt caching 行为 | - |
Tool Calling(工具调用)
AnthropicChatModel 支持工具调用。Claude 可以请求工具执行,但本身不会运行工具——实际执行交给 Java AI 处理。
对于大多数应用,建议用 ChatClient 加上自动注册的 ToolCallingAdvisor——参考 Tool Calling。如果你想自己驱动这个循环(比如把工具调用和 prompt caching 结合起来),可以看 ChatModel Tool Calling。
Tool Choice Options(工具选择选项)
通过 toolChoice 选项控制 Claude 选哪个工具:
// 强制 Claude 必须用某个工具(任何一个可用工具都行)
var options = AnthropicChatOptions.builder()
.toolChoice(ToolChoiceAny.builder().build())
.toolCallbacks(...)
.build();
// 强制 Claude 必须用某个指定名字的工具
var options = AnthropicChatOptions.builder()
.toolChoice(ToolChoiceTool.builder().name("getCurrentWeather").build())
.toolCallbacks(...)
.build();
// 完全禁止 Claude 调用任何工具
var options = AnthropicChatOptions.builder()
.toolChoice(ToolChoiceNone.builder().build())
.toolCallbacks(...)
.build();Extended Thinking(扩展思考)
Anthropic 的 Claude 模型支持一个 "thinking" 特性,可以让模型在给出最终答案之前先展示自己的推理过程。这个特性对需要逐步推理的复杂问题特别有用,比如数学、逻辑、分析类任务。
Supported Models(支持的模型)
- Claude 4 系列模型(
claude-opus-4-20250514、claude-sonnet-4-20250514) - Claude 3.7 Sonnet(
claude-3-7-sonnet-20250219)
Thinking Configuration(思考配置)
要启用 thinking,需要配置以下两项:
- 设置一个 thinking budget(思考预算,也就是给思考环节分配多少 token):
budgetTokens必须 >= 1024,并且小于maxTokens。 - 把温度设为
1.0:启用 thinking 时这是必须的。
// 启用思考,指定 token 预算
var options = AnthropicChatOptions.builder()
.model("claude-sonnet-4-20250514")
.temperature(1.0)
.maxTokens(16000)
.thinkingEnabled(10000L) // 预算必须 >= 1024 且 < maxTokens
.build();
// 让 Claude 自己自适应地决定要不要思考
var options = AnthropicChatOptions.builder()
.model("claude-sonnet-4-20250514")
.thinkingAdaptive()
.build();
// 显式关闭思考
var options = AnthropicChatOptions.builder()
.model("claude-sonnet-4-20250514")
.thinkingDisabled()
.build();白话解读
打个比方:思考就像学生做数学题在草稿纸上打草稿。SUMMARIZED 给你看一个精简版的草稿,OMITTED 直接把草稿纸撕掉,只留一个"我做过"的签字。答案本身的质量不变。
Non-Streaming Example(非流式示例)
var options = AnthropicChatOptions.builder()
.model("claude-sonnet-4-20250514")
.temperature(1.0)
.maxTokens(16000)
.thinkingEnabled(10000L)
.build();
ChatResponse response = chatModel.call(
new Prompt("Are there an infinite number of prime numbers such that n mod 4 == 3?", options));
for (Generation generation : response.getResults()) {
AssistantMessage message = generation.getOutput();
if (message.getMetadata().containsKey("signature")) {
// 这是一个思考块
System.out.println("Thinking: " + message.getText());
}
else if (message.getText() != null && !message.getText().isBlank()) {
// 这是最终的文本回复
System.out.println("Answer: " + message.getText());
}
}Multi-Modal Support(多模态支持)
Anthropic SDK 模块支持多模态输入,可以在 prompt 里同时传图片和 PDF 文档。
Image Input(图片输入)
// 从 classpath 加载图片
var imageResource = new ClassPathResource("/test-image.png");
var userMessage = UserMessage.builder()
.text("What do you see in this image?")
.media(List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageResource)))
.build();
ChatResponse response = chatModel.call(new Prompt(List.of(userMessage)));支持的图片格式:PNG、JPEG、GIF、WebP。
PDF Document Input(PDF 文档输入)
// 从 classpath 加载 PDF
var pdfResource = new ClassPathResource("/document.pdf");
var userMessage = UserMessage.builder()
.text("Please summarize this document.")
.media(List.of(new Media(new MimeType("application", "pdf"), pdfResource)))
.build();
ChatResponse response = chatModel.call(new Prompt(List.of(userMessage)));Citations(引用/出处标注)
Anthropic 的 Citations API 允许 Claude 在生成响应时引用所提供文档的具体部分。当 prompt 里带了可以被引用的文档时,Claude 可以标注信息来源,citation 元数据(字符范围、页码、或者内容块的索引)会出现在响应 metadata 里。
引用功能有助于:
- 准确性验证:用户可以把 Claude 的回答跟原始资料核对
- 透明度:清楚看到文档的哪一部分影响了回答
- 合规:满足受监管行业对"出处归属"的要求
- 信任:通过展示信息来源建立信心
Supported Models(支持的模型)
引用功能在 Claude 3.7 Sonnet 以及 Claude 4 系列模型(Opus 和 Sonnet)上支持。
Document Types(文档类型)
支持三种类型的引用文档:
| 类型 | 描述 |
|---|---|
| 纯文本(Plain Text) | 文本内容,带字符级引用 |
| PDF 文档,带页码级引用 | |
| 自定义内容(Custom Content) | 用户自定义的内容块,带块级引用 |
Creating Citation Documents(创建可被引用的文档)
// 用纯文本构造可被引用的文档
AnthropicCitationDocument document = AnthropicCitationDocument.builder()
.plainText("The Eiffel Tower was completed in 1889 in Paris, France. " +
"It stands 330 meters tall and was designed by Gustave Eiffel.")
.title("Eiffel Tower Facts")
.citationsEnabled(true) // 显式启用引用
.build();Using Citations in Requests(在请求里使用引用文档)
ChatResponse response = chatModel.call(
new Prompt(
"When was the Eiffel Tower built and how tall is it?",
AnthropicChatOptions.builder()
.model("claude-sonnet-4-20250514")
.maxTokens(1024)
.citationDocuments(document)
.build()
)
);Accessing Citations(拿到引用信息)
// 从 metadata 里取出引用列表
List<Citation> citations = (List<Citation>) response.getMetadata().get("citations");
for (Citation citation : citations) {
System.out.println("Document: " + citation.getDocumentTitle());
System.out.println("Location: " + citation.getLocationDescription());
System.out.println("Cited text: " + citation.getCitedText());
}Prompt Caching(提示缓存)
Anthropic 的 Prompt Caching 可以把跨多次 API 调用重复出现的上下文缓存起来,从而降低费用和延迟。Anthropic SDK 模块支持 prompt caching,可以配置策略、TTL,以及按消息类型分别设置。
Caching Strategies(缓存策略)
通过 AnthropicCacheStrategy 提供五种缓存策略:
| 策略 | 描述 |
|---|---|
NONE | 不缓存(默认)。不加任何 cache control header |
SYSTEM_ONLY | 只缓存 system message 的内容。占用 1 个 cache breakpoint(缓存断点,Anthropic 允许的缓存标记位置上限是 4 个) |
TOOLS_ONLY | 只缓存工具定义。占用 1 个缓存断点 |
SYSTEM_AND_TOOLS | 同时缓存 system message 和工具定义。占用 2 个缓存断点 |
CONVERSATION_HISTORY | 缓存 system message、工具定义以及对话消息。最多占用 4 个缓存断点 |
Basic Usage(基础用法)
// 用 SYSTEM_ONLY 策略,只缓存 system message
var options = AnthropicChatOptions.builder()
.model("claude-sonnet-4-20250514")
.maxTokens(1024)
.cacheOptions(AnthropicCacheOptions.builder()
.strategy(AnthropicCacheStrategy.SYSTEM_ONLY)
.build())
.build();
ChatResponse response = chatModel.call(
new Prompt(List.of(
new SystemMessage("You are an expert assistant with deep domain knowledge..."),
new UserMessage("What is the capital of France?")),
options));白话解读
prompt caching 的核心思想:对话开头那段"人设 + 上下文"每次都重复传,太浪费钱。Anthropic 允许你给它加几个"缓存断点",告诉它"从这到这,下次别再传了,直接读缓存",能省下不少 token 费用。
Structured Output(结构化输出)
结构化输出把 Claude 的响应约束成符合 JSON schema 的格式。Anthropic SDK 模块同时支持 Anthropic 的 effort 控制,用来在响应质量和速度之间做权衡。
Model Requirement(模型要求)
注意
结构化输出和 effort 控制需要 claude-sonnet-4-6 或更新模型。像 claude-sonnet-4-20250514 这种旧模型不支持这些特性。
JSON Schema Output(JSON schema 输出)
用 outputSchema 便捷方法把 Claude 的响应约束为指定的 JSON schema:
// 让 Claude 按指定 JSON schema 返回结果
var options = AnthropicChatOptions.builder()
.model("claude-sonnet-4-6")
.outputSchema("""
{
"type": "object",
"properties": {
"name": {"type": "string"},
"capital": {"type": "string"},
"population": {"type": "integer"}
},
"required": ["name", "capital"],
"additionalProperties": false
}
""")
.build();
ChatResponse response = chatModel.call(new Prompt("Tell me about France.", options));Effort Control(effort 控制)
控制 Claude 在响应上花多少算力。effort 越低,响应越快越便宜;effort 越高,推理越深入。
| Effort 级别 | 描述 |
|---|---|
LOW | 快速简洁,几乎不做推理 |
MEDIUM | 速度和深度之间的平衡 |
HIGH | 更深入的推理、更详细的回答 |
MAX | 最大算力,最充分的推理 |
// 用 LOW effort 追求速度和便宜
var options = AnthropicChatOptions.builder()
.model("claude-sonnet-4-6")
.effort(OutputConfig.Effort.LOW)
.build();Skills(技能)
Anthropic 的 Skills API 通过预打包的专门能力扩展了 Claude 的能力,可以用来生成文档。Skills 让 Claude 能生成真实可下载的文件——Excel 表格、PowerPoint 演示文稿、Word 文档、PDF——而不只是描述这些文件大概长啥样。
Supported Models(支持的模型)
Skills 在 Claude Sonnet 4、Claude Sonnet 4.5、Claude Opus 4 以及更新的模型上支持。
Pre-Built Anthropic Skills(Anthropic 预置技能)
Java AI 通过 AnthropicSkill 枚举提供了对 Anthropic 预置 skills 的类型安全访问:
| 技能 | 描述 | 生成的文件类型 |
|---|---|---|
XLSX | Excel 表格的生成和处理 | .xlsx |
PPTX | PowerPoint 演示文稿创建 | .pptx |
DOCX | Word 文档生成 | .docx |
PDF | PDF 文档创建 | .pdf |
Basic Usage(基础用法)
// 让 Claude 生成一份 Q1 2025 销售数据 Excel 表
ChatResponse response = chatModel.call(
new Prompt(
"Create an Excel spreadsheet with Q1 2025 sales data. " +
"Include columns for Month, Revenue, and Expenses with 3 rows of sample data.",
AnthropicChatOptions.builder()
.model(Model.CLAUDE_SONNET_4_5)
.maxTokens(4096)
.skill(AnthropicSkill.XLSX)
.build()
)
);Web Search(网页搜索)
Anthropic 的 Web Search 工具让 Claude 可以在对话中搜索网页,并用搜索结果生成带引用的回答。
- Web search 是一个内置的服务端工具——不需要额外的 tool callback
- Web search 结果会自动带 URL 的引用
- Web search 可以跟其他工具(函数调用、代码执行、Skills)在同一次请求里组合使用
Basic Usage(基础用法)
// 启用网页搜索
var webSearch = AnthropicWebSearchTool.builder().build();
ChatResponse response = chatModel.call(
new Prompt("What is the latest released version of Spring AI?",
AnthropicChatOptions.builder()
.webSearchTool(webSearch)
.build()));Sample Controller(示例 Controller)
@RestController
public class ChatController {
private final AnthropicChatModel chatModel;
public ChatController() {
var options = AnthropicChatOptions.builder()
.model("claude-sonnet-4-20250514")
.maxTokens(1024)
.apiKey(System.getenv("ANTHROPIC_API_KEY"))
.build();
this.chatModel = AnthropicChatModel.builder()
.options(options)
.build();
}
@GetMapping("/ai/generate")
public Map<String, String> generate(
@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return Map.of("generation", chatModel.call(message));
}
@GetMapping("/ai/generateStream")
public Flux<ChatResponse> generateStream(
@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
Prompt prompt = new Prompt(new UserMessage(message));
return chatModel.stream(prompt);
}
}Limitations(限制)
以下特性目前还不支持:
- Amazon Bedrock 后端
- Google Vertex AI 后端
这些特性计划在未来的版本中提供。
Azure OpenAI(Azure OpenAI 聊天)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/azure-openai-chat.html 📌 原文版本:Java AI 2.0.1
重要说明
从 Java AI 2.0.0-M5 开始,如果要访问部署在 Azure / Microsoft Foundry 上的 OpenAI 模型,应该改用 OpenAI Chat(而不是本文档所说的 Azure OpenAI Chat 模块)。
概述
本页面介绍 Java AI 中 Azure OpenAI(Azure 提供的 OpenAI 服务)聊天模型的集成方式。
白话解读
Azure OpenAI 就是微软把 OpenAI 的模型(比如 GPT-4)部署在自己云上的服务。Java AI 提供了专门的客户端来调用它。不过注意上面那个警告:新版本已经推荐直接用 OpenAI Chat 的客户端来访问 Azure 上的模型了。
前置要求(Prerequisites)
要使用 Azure OpenAI 聊天模型,你需要准备以下内容:
- 一个 Azure OpenAI 服务实例(在 Azure 门户中创建)
- 部署好的模型(deployment,比如 gpt-4、gpt-35-turbo 等)
- API Key 和 Endpoint(终结点 URL)
- 相应的 Java AI 依赖(starter)
Auto-Configuration(自动配置)
Java AI 提供了 Spring Boot 的自动配置(Auto-Configuration)支持,只要把依赖加入项目,再配置好属性(properties),就可以直接注入使用,无需手动创建 Bean。
说明
Auto-Configuration 是 Spring Boot 的核心特性之一:它会根据 classpath 上存在的类以及配置属性,自动装配好所需的组件。
Chat Properties(聊天属性)
在使用 Azure OpenAI 聊天模型时,可以通过配置属性来指定:
spring.ai.azure.openai.api-key:Azure OpenAI 的 API Keyspring.ai.azure.openai.endpoint:Azure 服务的终结点 URLspring.ai.azure.openai.chat.options.deployment-name:部署名称(deployment name)- 以及温度(temperature)、最大 token 数等常见推理参数
白话解读
这些属性就是告诉 Java AI:「去哪找 Azure 服务、用哪个模型、用什么参数聊天」。写进 application.properties 或 application.yml 就行。
Function Calling(函数调用)
Azure OpenAI 聊天模型支持 Function Calling(函数调用) 能力,也就是让模型在回答时主动「调用」你预先注册好的 Java 方法(函数),从而获取实时数据或执行操作。
白话解读
比如你写一个「查询天气」的函数,模型发现用户问天气时,就会自动请求调用这个函数,拿到结果后再组织成自然语言回答。
Sample Controller(示例控制器)
文档提供了一段示例 Controller 代码,用来演示如何在 Spring Boot 中调用 Azure OpenAI 聊天模型。
// 示例:使用 AzureOpenAiChatModel 进行聊天调用
@RestController
public class ChatController {
private final AzureOpenAiChatModel chatModel; // 注入 Azure OpenAI 聊天模型
public ChatController(AzureOpenAiChatModel chatModel) {
this.chatModel = chatModel; // 构造函数注入
}
@GetMapping("/ai/generate")
public Map<String, String> generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
// 调用模型的 call 方法,传入提示词(prompt),返回生成的文本
return Map.of("generation", this.chatModel.call(message));
}
}白话解读
这个 Controller 做了一件很简单的事:
- Spring 自动把
AzureOpenAiChatModel注入进来; - 用户访问
/ai/generate?message=xxx时,把 message 传给模型; - 把模型返回的文本包装成 JSON 返回给前端。
版本信息
- 当前稳定版本(Stable):2.0.1、1.1.8、1.0.9
- 快照版本(Snapshot):2.0.2-SNAPSHOT、1.1.9-SNAPSHOT
DeepSeek(DeepSeek 聊天)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/deepseek-chat.html 📌 原文版本:Java AI 2.0.1
Java AI(Spring 人工智能框架)支持 DeepSeek 提供的各种 AI 语言模型(AI language models)。你可以与 DeepSeek 语言模型进行交互,并基于 DeepSeek 模型创建多语言会话助手(multilingual conversational assistant)。
前置要求(Prerequisites)
你需要先在 DeepSeek 上创建一个 API key(API 密钥),才能访问 DeepSeek 的语言模型。
在 DeepSeek 注册页面创建账号,然后在 API Keys 页面生成一个 token(令牌)。
Java AI 项目定义了一个名为 spring.ai.deepseek.api-key 的配置属性(configuration property),你需要把它设置成从 API Keys 页面获取到的 API Key 值。
你可以在 application.properties 文件中设置这个配置属性:
spring.ai.deepseek.api-key=<your-deepseek-api-key>为了在处理 API key 这类敏感信息时增强安全性,你可以使用 Spring Expression Language(SpEL,Spring 表达式语言)来引用一个自定义环境变量(custom environment variable):
# 在 application.yml 中
spring:
ai:
deepseek:
api-key: ${DEEPSEEK_API_KEY}# 在你的环境变量或 .env 文件中
export DEEPSEEK_API_KEY=<your-deepseek-api-key>添加仓库和 BOM(Add Repositories and BOM)
Java AI 的构建产物(artifacts)发布在 Spring Milestone 和 Snapshot 仓库中。请参考 Artifact Repositories 章节把这些仓库添加到你的构建系统中。
为了便于依赖管理(dependency management),Java AI 提供了一个 BOM(bill of materials,物料清单),以确保整个项目中使用的 Java AI 版本保持一致。
自动配置(Auto-Configuration)
Java AI 为 DeepSeek Chat Model(DeepSeek 聊天模型)提供了 Spring Boot 自动配置(auto-configuration)。要启用它,请把下面的依赖添加到项目的 Maven pom.xml 文件中:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-deepseek</artifactId>
</dependency>或者添加到你的 Gradle build.gradle 文件中:
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-deepseek'
}聊天属性(Chat Properties)
重试属性(Retry Properties)
前缀 spring.ai.retry 用作属性前缀,让你可以配置 DeepSeek Chat 模型的重试机制(retry mechanism)。
| 属性 | 描述 | 默认值 |
|---|---|---|
spring.ai.retry.max-attempts | 最大重试次数(Maximum number of retry attempts)。 | 10 |
spring.ai.retry.backoff.initial-interval | 指数退避策略(exponential backoff policy)的初始休眠时长 | 2 秒 |
spring.ai.retry.backoff.multiplier | 退避间隔乘数(Backoff interval multiplier)。 | 5 |
spring.ai.retry.backoff.max-interval | 最大退避时长(Maximum backoff duration)。 | 3 分钟 |
spring.ai.retry.on-client-errors | 如果为 false,则抛出 NonTransientAiException,并且对 4xx 客户端错误码不进行重试 | false |
spring.ai.retry.exclude-on-http-codes | 不应触发重试的 HTTP 状态码列表 | 空 |
spring.ai.retry.on-http-codes | 应触发重试的 HTTP 状态码列表 | 空 |
连接属性(Connection Properties)
前缀 spring.ai.deepseek 用作属性前缀,让你可以连接到 DeepSeek。
| 属性 | 描述 | 默认值 |
|---|---|---|
spring.ai.deepseek.base-url | 要连接的 URL。 | https://api.deepseek.com |
spring.ai.deepseek.api-key | API Key。 | - |
配置属性(ConfigurationProperties)
聊天自动配置(chat auto-configurations)的启用和禁用现在通过前缀为 spring.ai.model.chat 的顶层属性(top level properties)来配置。
- 启用:
spring.ai.model.chat=deepseek(默认情况下就是启用的) - 禁用:
spring.ai.model.chat=none(或任何与 deepseek 不匹配的值)
这一改动是为了支持多个模型的配置(configuration of multiple models)。
前缀 spring.ai.deepseek.chat 是用来配置 DeepSeek 聊天模型实现的属性前缀。
| 属性 | 描述 | 默认值 |
|---|---|---|
spring.ai.model.chat | 启用 DeepSeek 聊天模型。 | deepseek |
spring.ai.deepseek.chat.base-url | 可选,覆盖 spring.ai.deepseek.base-url,提供一个聊天专用的 URL。 | https://api.deepseek.com/ |
spring.ai.deepseek.chat.api-key | 可选,覆盖 spring.ai.deepseek.api-key,提供一个聊天专用的 API key。 | - |
spring.ai.deepseek.chat.completions-path | 聊天补全接口(chat completions endpoint)的路径。 | /chat/completions |
spring.ai.deepseek.chat.beta-prefix-path | beta 特性接口(beta feature endpoint)的前缀路径。 | /beta |
spring.ai.deepseek.chat.model | 要使用的模型 ID。可用 deepseek-v4-flash、deepseek-v4-pro、deepseek-chat 或 deepseek-reasoner。 | deepseek-v4-flash |
spring.ai.deepseek.chat.frequency-penalty | 介于 -2.0 到 2.0 之间的数值。正值会惩罚新 token 在目前文本中已有的频率。 | 0.0f |
spring.ai.deepseek.chat.max-tokens | 在聊天补全中要生成的最大 token 数量。 | - |
spring.ai.deepseek.chat.presence-penalty | 介于 -2.0 到 2.0 之间的数值。正值会惩罚已出现过的 token。 | 0.0f |
spring.ai.deepseek.chat.stop | 最多 4 个停止序列(sequences)。 | - |
spring.ai.deepseek.chat.temperature | 采样温度(sampling temperature),介于 0 到 2 之间。 | 1.0F |
spring.ai.deepseek.chat.top-p | 核采样(nucleus sampling)的概率质量。 | 1.0F |
spring.ai.deepseek.chat.logprobs | 是否返回输出 token 的对数概率(log probabilities)。 | - |
spring.ai.deepseek.chat.top-logprobs | 一个介于 0 到 20 之间的整数。 | - |
spring.ai.deepseek.chat.thinking.type | 控制思考模式(thinking mode)与非思考模式之间的切换。 | - |
spring.ai.deepseek.chat.reasoning-effort | 控制 DeepSeek 模型的推理强度级别(reasoning effort level)。 | - |
spring.ai.deepseek.chat.tool-callbacks | 要注册到 ChatModel 的工具回调(Tool Callbacks)。 | - |
白话解读
简单说就是:通用属性 spring.ai.deepseek.* 是"全局默认值",而 spring.ai.deepseek.chat.* 是"聊天专用值"。专用值一旦设置了就会覆盖全局值。这样你可以一个账号跑这个模型,另一个账号跑那个模型。
运行时选项(Runtime Options)
DeepSeekChatOptions.java 提供了模型配置,比如要使用的模型、温度、频率惩罚等。
在启动时,默认选项可以通过 DeepSeekChatModel(api, options) 构造函数或 spring.ai.deepseek.chat.* 属性来配置。
在运行时,你可以通过给 Prompt 调用添加新的、请求专用的选项来覆盖默认选项。例如,为某个特定请求覆盖默认模型和温度:
ChatResponse response = chatModel.call(
new Prompt(
"Generate the names of 5 famous pirates. Please provide the JSON response without any code block markers such as ```json```.", // 生成 5 个著名海盗的名字。请提供不带 ```json``` 这类代码块标记的 JSON 响应。
DeepSeekChatOptions.builder()
.withModel(DeepSeekApi.ChatModel.DEEPSEEK_V4_PRO.getValue()) // 指定使用 deepseek-v4-pro 模型
.withTemperature(0.8f) // 温度设为 0.8,输出更随机
.build()
));示例控制器(自动配置)(Sample Controller (Auto-Configuration))
创建一个新的 Spring Boot 项目,并把 spring-ai-starter-model-deepseek 添加到你的 pom(或 gradle)依赖中。
在 src/main/resources 目录下添加一个 application.properties 文件,用来启用并配置 DeepSeek Chat 模型:
spring.ai.deepseek.api-key=YOUR_API_KEY
spring.ai.deepseek.chat.model=deepseek-v4-pro
spring.ai.deepseek.chat.temperature=0.8把 api-key 替换成你的 DeepSeek 凭证(credentials)。
这会创建一个 DeepSeekChatModel 实现,你可以把它注入到你的类里。下面是一个简单的 @Controller 类示例,它使用聊天模型进行文本生成:
@RestController
public class ChatController {
private final DeepSeekChatModel chatModel;
@Autowired
public ChatController(DeepSeekChatModel chatModel) {
this.chatModel = chatModel;
}
@GetMapping("/ai/generate")
public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
// 调用聊天模型,返回生成的文本
return Map.of("generation", chatModel.call(message));
}
@GetMapping("/ai/generateStream")
public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
// 构造 Prompt,包含用户消息
var prompt = new Prompt(new UserMessage(message));
// 以流式方式返回聊天响应
return chatModel.stream(prompt);
}
}工具调用(Tool Calling)
DeepSeekChatModel 支持工具调用(tool calling)。模型可以请求执行工具,但它自己并不运行工具——Java AI 负责执行。
对大多数应用程序来说,请使用 ChatClient 搭配自动注册的 ToolCallingAdvisor——参见 Tool Calling 章节。对于需要你自己驱动循环(drive the loop yourself)的低层控制,参见 ChatModel Tool Calling 章节。
聊天前缀补全(Chat Prefix Completion)
聊天前缀补全(chat prefix completion)遵循 Chat Completion API 的规范,即用户提供一个 assistant 的前缀消息(prefix message),让模型补全消息的剩余部分。
使用前缀补全时,用户必须确保 messages 列表中的最后一条消息是一个 DeepSeekAssistantMessage。
下面是一个聊天前缀补全的完整 Java 代码示例。在这个例子中,我们把 assistant 的前缀消息设置为 ```python\n,以强制模型输出 Python 代码,并把 stop 参数设置为 ['']`,以防止模型给出额外的解释。
@RestController
public class CodeGenerateController {
private final DeepSeekChatModel chatModel;
@Autowired
public ChatController(DeepSeekChatModel chatModel) {
this.chatModel = chatModel;
}
@GetMapping("/ai/generatePythonCode")
public String generate(@RequestParam(value = "message", defaultValue = "Please write quick sort code") String message) {
// 构造用户消息
UserMessage userMessage = new UserMessage(message);
// 构造 assistant 前缀消息,内容为 python 代码块起始标记,并标记为 prefix
Message assistantMessage = DeepSeekAssistantMessage.builder().content("```python\\n").prefix(true).build();
// 构造 Prompt,包含用户消息和 assistant 前缀消息,并设置停止序列
Prompt prompt = new Prompt(List.of(userMessage, assistantMessage), ChatOptions.builder().stopSequences(List.of("```")).build());
// 调用模型
ChatResponse response = chatModel.call(prompt);
// 返回生成的文本
return response.getResult().getOutput().getText();
}
}推理支持(Reasoning Support)
你可以使用 DeepSeekAssistantMessage 来获取支持该特性的模型生成的 CoT(Chain of Thought,思维链)内容。
public void deepSeekReasoningExample() {
DeepSeekChatOptions promptOptions = DeepSeekChatOptions.builder()
.build();
Prompt prompt = new Prompt("9.11 and 9.8, which is greater?", promptOptions); // 9.11 和 9.8 哪个更大?
ChatResponse response = chatModel.call(prompt);
// 获取模型生成的 CoT 内容
DeepSeekAssistantMessage deepSeekAssistantMessage = (DeepSeekAssistantMessage) response.getResult().getOutput();
String reasoningContent = deepSeekAssistantMessage.getReasoningContent(); // 获取推理内容
String text = deepSeekAssistantMessage.getText(); // 获取最终回答文本
}思考模式(Thinking Mode)
DeepSeek 模型支持在思考模式(thinking mode)和非思考模式(non-thinking mode)之间切换。思考模式可以通过 Thinking 选项来控制,它接受 Thinking.ENABLED(思考模式)或 Thinking.DISABLED(非思考模式)。当思考被禁用时,模型不会产生任何推理内容(reasoning content)。
public void deepSeekThinkingExample() {
DeepSeekChatOptions promptOptions = DeepSeekChatOptions.builder()
.thinking(Thinking.DISABLED) // 禁用思考模式
.build();
Prompt prompt = new Prompt("9.11 and 9.8, which is greater?", promptOptions);
ChatResponse response = chatModel.call(prompt);
DeepSeekAssistantMessage deepSeekAssistantMessage = (DeepSeekAssistantMessage) response.getResult().getOutput();
// 思考被禁用时不会产生推理内容
String reasoningContent = deepSeekAssistantMessage.getReasoningContent();
String text = deepSeekAssistantMessage.getText();
}思考模式也可以通过 enableThinking() 和 disableThinking() 这两个 builder 便捷方法(convenience methods)来切换,或者通过 spring.ai.deepseek.chat.thinking.type 属性进行全局配置。
推理强度(Reasoning Effort)
DeepSeek 模型允许你通过 ReasoningEffort 选项控制推理强度级别(reasoning effort level)。对于普通请求,ReasoningEffort.HIGH 是默认值;而对于复杂的 Agent 风格请求(如 Claude Code、OpenCode),会自动使用 ReasoningEffort.MAX。
public void deepSeekReasoningEffortExample() {
DeepSeekChatOptions promptOptions = DeepSeekChatOptions.builder()
.reasoningEffort(ReasoningEffort.MAX) // 设置推理强度为 max
.build();
Prompt prompt = new Prompt("9.11 and 9.8, which is greater?", promptOptions);
ChatResponse response = chatModel.call(prompt);
DeepSeekAssistantMessage deepSeekAssistantMessage = (DeepSeekAssistantMessage) response.getResult().getOutput();
String reasoningContent = deepSeekAssistantMessage.getReasoningContent(); // 获取推理内容
String text = deepSeekAssistantMessage.getText(); // 获取最终回答文本
}推理强度也可以通过 reasoningEffortHigh() 和 reasoningEffortMax() 这两个 builder 便捷方法来设置,或者通过 spring.ai.deepseek.chat.reasoning-effort 属性进行全局配置。
推理模型多轮对话(Reasoning Model Multi-Round Conversation)
在对话的每一轮中,模型都会输出 CoT(reasoning_content)和最终回答(content)。在下一轮对话中,之前轮次的 CoT 不会被拼接到上下文(context)中。
Docker Model Runner(Docker Model Runner 聊天)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/dmr-chat.html 📌 原文版本:Java AI 2.0.1
Docker Model Runner 是一个 AI 推理引擎(Inference Engine),提供来自不同厂商的各种模型。
Java AI 通过复用现有的 OpenAI 后端的 ChatClient 来集成 Docker Model Runner。做法是:把 base URL 设置成 localhost:12434/engines/v1,然后选择一个提供的 LLM(大语言模型)即可。
可以参考 DockerModelRunnerWithOpenAiChatModelIT.java 测试类,里面有 Java AI 与 Docker Model Runner 联用的示例。
前置要求(Prerequisite)
- 下载 Docker Desktop for Mac 4.40.0。
启用 Model Runner 有两种方式,选一个就行:
方式一(Option 1):
- 启用 Model Runner:
docker desktop enable model-runner --tcp 12434 - 把 base-url 设置成
localhost:12434/engines/v1
方式二(Option 2):
- 启用 Model Runner:
docker desktop enable model-runner - 使用 Testcontainers(一个用于集成测试的容器库),base-url 配置如下:
@Container
private static final DockerModelRunnerContainer DMR = new DockerModelRunnerContainer("alpine/socat:1.7.4.3-r0");
@Bean
public OpenAiChatModel chatModel() {
// 从容器对象拿到 OpenAI 兼容的访问地址
var baseUrl = DMR.getOpenAIEndpoint();
return OpenAiChatModel.builder()
// 自定义 OpenAI 配置:设置 baseUrl 和任意 apiKey
.options(OpenAiChatOptions.builder().baseUrl(baseUrl).apiKey("test").build())
.build();
}更多关于 Docker Model Runner 的内容,可以读这篇博客:Run LLMs Locally with Docker(用 Docker 在本地跑大模型)。
白话解读
Docker Model Runner 本质上就是把各种 LLM 包成了一个 OpenAI 兼容的服务(也就是说接口长得跟 OpenAI 一样),所以 Java AI 直接拿 OpenAI 的 ChatClient 就能用,连新写一套客户端都省了。
自动配置(Auto-Configuration)
提示
从 1.0.0.M7 版本开始,Java AI starter 模块的 artifactId 命名规则改了——依赖名字现在要按新的命名规范来写(模型、向量库、MCP starter 都变了)。具体迁移细节请看升级说明。
Java AI 为 OpenAI Chat Client 提供了 Spring Boot 自动配置。在项目 pom.xml 里加上下面这个依赖就能启用:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>或者在 Gradle 的 build.gradle 里写:
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-openai'
}记得去依赖管理那一节把 Java AI BOM(物料清单,统一管理版本号)加到构建文件里。
聊天属性(Chat Properties)
重试属性(Retry Properties)
属性前缀 spring.ai.retry 用来配置 OpenAI 聊天模型的重试机制。
| 属性 | 说明 | 默认值 |
|---|---|---|
spring.ai.retry.max-attempts | 最大重试次数。 | 10 |
spring.ai.retry.backoff.initial-interval | 指数退避策略(每次重试间隔越来越长)的初始等待时长。 | 2 sec. |
spring.ai.retry.backoff.multiplier | 退避间隔的倍数。 | 5 |
spring.ai.retry.backoff.max-interval | 退避时长的上限。 | 3 min. |
spring.ai.retry.on-client-errors | 如果设为 false,遇到 4xx 客户端错误码时直接抛 NonTransientAiException,不再重试。 | false |
连接属性(Connection Properties)
属性前缀 spring.ai.openai 用来配置 OpenAI 的连接信息。
| 属性 | 说明 | 默认值 |
|---|---|---|
spring.ai.openai.base-url | 要连接的 URL。必须设为 localhost:12434/engines/v1。 | - |
spring.ai.openai.api-key | 任意字符串。 | - |
配置属性(ConfigurationProperties)
从某个版本开始,开启/关闭聊天自动配置改用顶层属性 spring.ai.model.chat 来做。
- 启用:
spring.ai.model.chat=openai(默认就是启用的) - 禁用:
spring.ai.model.chat=none(或者任何不等于openai的值)
这样做的好处是可以在同一个应用里配置多个模型。
属性前缀 spring.ai.openai.chat 用来配置 OpenAI 聊天模型的具体实现。
| 属性 | 说明 | 默认值 |
|---|---|---|
spring.ai.model.chat | 启用 OpenAI 聊天模型。 | openai |
spring.ai.openai.chat.base-url | 可选,覆盖 spring.ai.openai.base-url,提供聊天专用的 URL。必须设为 localhost:12434/engines/v1。 | - |
spring.ai.openai.chat.api-key | 可选,覆盖 spring.ai.openai.api-key,提供聊天专用的 api-key。 | - |
spring.ai.openai.chat.model | 要使用的 LLM 模型。 | - |
spring.ai.openai.chat.temperature | 采样温度(控制生成的随机性)。值越高输出越随机,越低越稳定、有套路。 | 0.8 |
spring.ai.openai.chat.frequency-penalty | 范围 -2.0 到 2.0。正值会惩罚已经在文中出现过的词。 | 0.0f |
spring.ai.openai.chat.max-tokens | 单次聊天补全最多生成多少 token(模型处理文字的最小单位)。 | - |
spring.ai.openai.chat.n | 每条输入消息生成多少条聊天补全结果。建议保持为 1 以省成本。 | 1 |
spring.ai.openai.chat.presence-penalty | 范围 -2.0 到 2.0。正值会惩罚已经出现过的主题。 | - |
spring.ai.openai.chat.response-format | 指定模型必须输出的格式。设成 { "type": "json_object" } 可以开启 JSON 模式。 | - |
spring.ai.openai.chat.seed | Beta 功能。如果指定了,系统会尽量做确定性采样。 | - |
spring.ai.openai.chat.stop | 最多 4 个序列,遇到这些序列时 API 就停止生成后续 token。 | - |
spring.ai.openai.chat.top-p | 核采样(nucleus sampling),即只考虑概率质量(概率总和)排名前 p 的 token。 | - |
spring.ai.openai.chat.tools | 模型可以调用的工具列表,目前只支持函数(function)。 | - |
spring.ai.openai.chat.tool-choice | 控制模型是否调用函数、调用哪个。 | - |
spring.ai.openai.chat.user | 代表最终用户的唯一标识,可以帮助 OpenAI 监控和检测滥用。 | - |
spring.ai.openai.chat.stream-usage | 仅流式模式下有效。设为 true 后,会多返回一个 chunk(数据块),里面包含整个请求的 token 用量统计。 | false |
spring.ai.openai.chat.tool-callbacks | 注册到 ChatModel 的工具回调。 | - |
所有以 spring.ai.openai.chat 开头的属性,都可以在运行时通过给 Prompt 调用添加请求级的 Runtime Options 来覆盖。
运行时选项(Runtime Options)
OpenAiChatOptions.java 提供了模型配置项,比如用哪个模型、temperature 多大、frequency-penalty 多少等等。
启动时,可以通过 OpenAiChatModel(api, options) 构造函数,或者 spring.ai.openai.chat.* 这些属性来设置默认选项。
运行时,可以通过给 Prompt 调用附加请求级的选项来覆盖默认值。比如想为某个特定请求覆盖默认模型和 temperature,可以这么写:
ChatResponse response = chatModel.call(
new Prompt(
"Generate the names of 5 famous pirates.",
OpenAiChatOptions.builder()
// 这里用 ai/gemma3:4B-F16 这个模型覆盖默认模型
.model("ai/gemma3:4B-F16")
.build()
));工具调用(Tool Calling)
Docker Model Runner 在所选模型支持工具调用时也支持工具调用。Java AI 负责处理工具执行循环。
大部分应用里,推荐用 ChatClient 配合自动注册的 ToolCallingAdvisor(参见 Tool Calling 章节)。如果你想要自己手动控制整个循环,可以看 ChatModel Tool Calling。
示例 Controller(Sample Controller)
新建一个 Spring Boot 项目,在 pom.xml(或 gradle)依赖里加上 spring-ai-starter-model-openai。
在 src/main/resources 目录下新建 application.properties 文件,启用并配置 OpenAI 聊天模型:
spring.ai.openai.api-key=test
spring.ai.openai.base-url=http://localhost:12434/engines/v1
spring.ai.openai.chat.model=ai/gemma3:4B-F16
# Docker Model Runner 不支持 embedding(向量嵌入),所以这里要关掉
spring.ai.model.embedding=none下面是一个简单的 @Controller 类,用聊天模型来生成文本:
@RestController
public class ChatController {
private final OpenAiChatModel chatModel;
@Autowired
public ChatController(OpenAiChatModel chatModel) {
// 注入 OpenAI 聊天模型 Bean
this.chatModel = chatModel;
}
@GetMapping("/ai/generate")
public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
// 普通文本生成接口,返回一个包含生成内容的 map
return Map.of("generation", this.chatModel.call(message));
}
@GetMapping("/ai/generateStream")
public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
// 流式生成接口,返回 Flux<ChatResponse>(响应式流,可以一段一段地往外推结果)
Prompt prompt = new Prompt(new UserMessage(message));
return this.chatModel.stream(prompt);
}
}白话解读
两个接口其实干的是同一件事——用聊天模型回答用户消息。/ai/generate 等模型把整段话生成完再一次性返回;/ai/generateStream 则是模型边生成边往外吐结果,调用方可以实时拿到部分内容,体验上更顺滑(类似 ChatGPT 那种打字机效果)。
Google GenAI(Google GenAI 聊天)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/google-genai-chat.html 📌 原文版本:Java AI 2.0.1
Google GenAI API(Google 生成式 AI 接口)让开发者可以通过 Gemini Developer API(Gemini 开发者 API) 或 Vertex AI 来调用 Google 的 Gemini 大模型,从而构建生成式 AI 应用。Google GenAI API 支持多模态 prompt(提示词)输入,输出可以是文本或代码。多模态模型(multimodal model)能同时处理图像、视频、文本等多种模态(modality)的信息。例如,你可以给模型发一张饼干的照片,让它给出对应的饼干食谱。
Gemini 是 Google DeepMind 开发的一系列生成式 AI 模型,专门为多模态场景设计。Gemini API 让你可以使用多种模型,如 Gemini Flash-Lite、Gemini Flash 或 Gemini Pro。
该实现支持两种认证模式:
- Gemini Developer API(Gemini 开发者 API):使用 API key(密钥)快速做原型开发和调试。
- Vertex AI:使用 Google Cloud 凭据(credentials),适合生产环境部署,具备企业级特性。
Prerequisites(前置要求)
从以下两种认证方式中选择一种:
Option 1: Gemini Developer API (API Key)(方式一:Gemini 开发者 API,使用 API key)
- 从 Google AI Studio 获取 API key。
- 将 API key 设置为环境变量,或写在应用的属性配置里。
Option 2: Vertex AI (Google Cloud)(方式二:Vertex AI,使用 Google Cloud)
- 安装适合你操作系统的
gcloudCLI(Google Cloud 命令行工具)。 - 运行以下命令完成认证。把
PROJECT_ID换成你的 Google Cloud 项目 ID,把ACCOUNT换成你的 Google Cloud 用户名。
gcloud config set project <PROJECT_ID> &&
gcloud auth application-default login <ACCOUNT>Auto-Configuration(自动配置)
注意
Java AI 的 auto-configuration(自动配置)和 starter 模块(起步依赖)的 artifact 名称(制品名)发生了重大变化,请参考升级说明(upgrade notes)获取更多信息。
Java AI 为 Google GenAI Chat Client 提供了 Spring Boot 自动配置。要启用它,请在项目的 Maven pom.xml 或 Gradle build.gradle 构建文件中添加以下依赖:
Maven
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-google-genai</artifactId>
</dependency>Gradle
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-google-genai'
}请参考 Dependency Management(依赖管理)一节,把 Java AI BOM 加入构建文件。
白话解读
BOM(Bill of Materials,物料清单)就是帮你统一管理所有 Java AI 相关依赖的版本号,避免版本冲突。加上 BOM 后,依赖就不需要再写版本号了。
Chat Properties(聊天属性)
聊天自动配置的启用/禁用,现在改为通过顶层属性 spring.ai.model.chat 前缀来配置。
- 启用:
spring.ai.model.chat=google-genai(默认即为启用状态) - 禁用:
spring.ai.model.chat=none(或任何不等于google-genai的值)
这样改是为了支持同时配置多个模型。
Connection Properties(连接属性)
属性前缀 spring.ai.google.genai,用于连接 Google GenAI。
| 属性 | 说明 | 默认值 |
|---|---|---|
spring.ai.model.chat | 启用 Chat Model(聊天模型)客户端 | google-genai |
spring.ai.google.genai.api-key | Gemini Developer API 的 API key。提供后,客户端会使用 Gemini Developer API 而不是 Vertex AI。 | - |
spring.ai.google.genai.project-id | Google Cloud Platform 项目 ID(Vertex AI 模式必填) | - |
spring.ai.google.genai.location | Google Cloud region(区域,Vertex AI 模式必填) | - |
spring.ai.google.genai.credentials-uri | Google Cloud 凭据的 URI。提供后会据此创建 GoogleCredentials 实例用于认证。 | - |
Chat Model Properties(聊天模型属性)
属性前缀 spring.ai.google.genai.chat,用于配置 Google GenAI Chat 的聊天模型实现。
| 属性 | 说明 | 默认值 |
|---|---|---|
spring.ai.google.genai.chat.model | 要使用的 Google GenAI Chat 模型,包括 gemini-2.5-flash、gemini-2.5-flash-lite、gemini-2.5-pro、gemini-3.1-pro-preview、gemini-3.1-flash-lite 和 gemini-3.5-flash。 | gemini-2.5-flash |
spring.ai.google.genai.chat.response-mime-type | 生成候选文本的输出响应 mime type(媒体类型)。text/plain(默认,文本输出)或 application/json(JSON 响应)。 | - |
spring.ai.google.genai.chat.google-search-retrieval | 是否使用 Google 搜索 Grounding(接地/检索增强)功能。true 或 false,默认 false。 | - |
spring.ai.google.genai.chat.include-server-side-tool-invocations | 为 true 时,API 响应会在响应 metadata(元数据)中包含服务端工具调用与响应(例如 Google Search 调用),方便观测服务端工具的使用情况。仅 Gemini Developer API(MLDev)支持,Vertex AI 不支持。 | false |
spring.ai.google.genai.chat.temperature | 控制输出的随机性。取值范围 [0.0, 1.0](含端点)。越接近 1.0,输出越多样;越接近 0.0,输出越不意外(更确定)。 | - |
spring.ai.google.genai.chat.top-k | 采样时考虑的最大 token(词元)数。 | - |
spring.ai.google.genai.chat.top-p | 采样时考虑的最大累计概率。 | - |
spring.ai.google.genai.chat.candidate-count | 返回的生成响应消息数量。取值范围 [1, 8](含端点)。 | 1 |
spring.ai.google.genai.chat.max-output-tokens | 生成的最大 token 数。 | - |
spring.ai.google.genai.chat.frequency-penalty | 频率惩罚,用于减少重复。 | - |
spring.ai.google.genai.chat.presence-penalty | 存在惩罚,用于减少重复。 | - |
spring.ai.google.genai.chat.thinking-budget | 思考过程的思考预算(thinking budget)。 | - |
spring.ai.google.genai.chat.thinking-level | 模型应生成的思考 token 级别。有效值:LOW、HIGH、THINKING_LEVEL_UNSPECIFIED。 | - |
spring.ai.google.genai.chat.include-thoughts | 为 function calling(函数调用)启用 thought signatures(思考签名)。Gemini 3 Pro 必须开启,否则工具调用循环中会出现校验错误。 | false |
spring.ai.google.genai.chat.tool-callbacks | 要向 ChatModel 注册的 Tool Callbacks(工具回调)。 | - |
spring.ai.google.genai.chat.safety-settings | 控制安全过滤器的 safety settings(安全设置)列表。 | - |
spring.ai.google.genai.chat.cached-content-name | 本次请求要使用的 cached content(缓存内容)名称。 | - |
spring.ai.google.genai.chat.use-cached-content | 是否使用可用的缓存内容。当为 true 且设置了 cached-content-name 时,系统会使用缓存内容。 | false |
spring.ai.google.genai.chat.auto-cache-threshold | 当 prompt 超过此 token 阈值时自动缓存。 | - |
spring.ai.google.genai.chat.auto-cache-ttl | 自动缓存内容的 TTL(time-to-live,存活时间),ISO-8601 格式(如 PT1H 表示 1 小时)。 | PT1H |
spring.ai.google.genai.chat.service-tier | 请求使用的 service tier(服务层级)。有效值:STANDARD、PRIORITY、FLEX。 | - |
spring.ai.google.genai.chat.tool-choice.mode | 当提供了工具时,控制模型如何选择函数。 | - |
spring.ai.google.genai.chat.tool-choice.allowed-function-names | 允许模型调用的函数名,逗号分隔。 | - |
所有以 spring.ai.google.genai.chat 开头的属性,都可以在运行时通过在 Prompt 调用中添加请求级 Runtime options(运行时选项)来覆盖。
Runtime Options(运行时选项)
GoogleGenAiChatOptions.java 提供了模型配置,例如 temperature、topK 等。
启动时,可以通过 GoogleGenAiChatModel(client, options) 构造函数或 spring.ai.google.genai.chat.* 属性配置默认选项。
运行时,可以在 Prompt 调用中添加请求级的选项来覆盖默认值。例如,为某次请求单独覆盖默认 temperature:
ChatResponse response = chatModel.call(
new Prompt(
"Generate the names of 5 famous pirates.", // 提示词:生成 5 个著名海盗的名字
GoogleGenAiChatOptions.builder()
.temperature(0.4) // 覆盖温度参数为 0.4
.build()
));Tool Calling(工具调用)
GoogleGenAiChatModel 支持 tool calling(工具调用)。模型可以请求执行工具,但它自己不运行工具——工具的执行由 Java AI 负责。
对大多数应用来说,推荐使用 ChatClient 并配合自动注册的 ToolCallingAdvisor —— 参见 Tool Calling。若需要底层控制、自己驱动循环,参见 ChatModel Tool Calling。
关于 Google 内置工具(Search、Maps、URL Context)以及如何与客户端函数调用组合使用,见下方 Server-Side Tool Invocations(服务端工具调用)。
Tool Choice(工具选择)
GoogleGenAiChatOptions.ToolChoice 用于配置当提供了工具时模型如何选择函数。它对应 Google GenAI 的 FunctionCallingConfig。
| 模式 | 行为 |
|---|---|
AUTO | 模型自行决定是调用函数还是返回自然语言响应(默认行为)。 |
ANY | 模型总是预测一个函数调用。设置 allowedFunctionNames 后,调用范围被限制在这些函数内。 |
VALIDATED | 模型可以调用函数或返回自然语言响应。设置 allowedFunctionNames 后,调用范围被限制在这些函数内。 |
NONE | 模型不调用任何函数,返回自然语言响应。 |
allowedFunctionNames 仅在 mode 为 ANY 或 VALIDATED 时生效;在 AUTO 和 NONE 下会被静默忽略。
Programmatic Configuration(编程方式配置)
ChatResponse response = chatModel.call(
new Prompt(
"What is the weather in Paris?", // 提示词:巴黎天气如何?
GoogleGenAiChatOptions.builder()
.toolChoice(new GoogleGenAiChatOptions.ToolChoice(
GoogleGenAiChatOptions.ToolChoice.Mode.ANY, // 强制调用函数
List.of("get_weather"))) // 只允许调用 get_weather
.build()
));Server-Side Tool Invocations(服务端工具调用)
当通过 googleSearchRetrieval(true) 启用 Google Search 或其他服务端工具时,模型在服务端执行这些工具。默认情况下,这些调用对客户端是不可见的——你只能看到最终文本响应。设置 includeServerSideToolInvocations(true) 可以让 API 在响应内容中包含服务端的工具调用和响应,从而让你观测到模型搜索了什么、收到了什么结果。
该特性仅 Gemini Developer API(MLDev / API key 认证)支持,Vertex AI 不支持。
服务端工具调用是只用于观测的(observational only)——客户端不会执行它们。它们被单独放在 metadata 里,与客户端函数调用区分开,以免干扰工具执行循环。
白话解读
简单说:Google Search 这种工具是 Google 在服务端跑的,你只能"看"到它调了啥;而你自己写的工具(比如查天气)是本地跑的。两者可以共存,但分开对待。
Thinking Configuration(思考配置)
Gemini 模型支持 "thinking"(思考)能力,允许模型在生成响应前做更深的推理。它由 ThinkingConfig 控制,包含三个相关选项:thinkingBudget、thinkingLevel 和 includeThoughts。
Thinking Level(思考级别)
thinkingLevel 选项控制模型生成的推理 token 深度。支持 thinking 的模型(如 Gemini 3 Pro Preview)可使用。
| 值 | 说明 |
|---|---|
THINKING_LEVEL_UNSPECIFIED | 模型使用默认行为。 |
MINIMAL | 对大多数查询等同于"不思考"设置,把延迟降到最低。 |
LOW | 低级思考,推理 token 最少。 |
MEDIUM | 对大多数任务而言的均衡思考。 |
HIGH | 大量思考,用于需要深度分析和逐步推理的复杂问题。 |
Thinking Budget(思考预算)
thinkingBudget 选项为思考过程设置 token 预算:
- 正值:思考的最大 token 数(如 8192)
- 零(0):完全禁用思考
- 未设置:模型根据查询复杂度自行决定
Option Compatibility(选项兼容性)
thinkingLevel 和 thinkingBudget 是互斥的。同一个请求里不能同时使用——否则会触发 API 错误。
- Gemini 3.x 模型用
thinkingLevel。Gemini 3 Pro 只支持LOW和HIGH;Gemini 3 Flash 支持所有级别(MINIMAL、LOW、MEDIUM、HIGH)。 - Gemini 2.5 系列模型用
thinkingBudget(token 数)。
注意
- 在不支持的模型(如 Gemini 2.5 或更早)上使用
thinkingLevel会触发 API 错误。 - 在 Gemini 3 Pro 模型上使用
MINIMAL或MEDIUM会抛IllegalArgumentException。 - 启用思考特性会增加 token 使用量和 API 成本。请根据查询复杂度酌情使用。
Thought Signatures(思考签名)
Gemini 3 Pro 引入了 thought signatures(思考签名),是一种不透明的字节数组(byte array),用于在 function calling(函数调用)过程中保留模型的推理上下文。启用 includeThoughts 后,模型会返回思考签名,必须在同一轮(turn)的工具调用循环中把它们原样传回去。
重要
思考签名校验只作用于当前轮——具体是在模型发起函数调用的工具调用循环中(包括并行和顺序调用)。API 不会对会话历史中之前轮的思考签名做校验。
Automatic Handling via ChatClient (Recommended)(通过 ChatClient 自动处理,推荐)
使用 ChatClient 配合 ToolCallingAdvisor(推荐做法)时,Java AI 会自动处理思考签名:
- 从模型响应中提取思考签名;
- 在发送函数响应回去时,把它们附加到正确的
functionCallpart 上; - 在单轮内的函数调用中(包括并行和顺序调用)正确传播。
String response = ChatClient.create(this.chatModel)
.prompt("What's the weather like in Boston?") // 波士顿天气如何?
.options(GoogleGenAiChatOptions.builder()
.model("gemini-3.1-pro-preview")
.includeThoughts(true) // 启用思考签名
.build())
.tools(weatherFunction)
.call()
.content();Multimodal(多模态)
多模态(Multimodality)指模型同时理解和处理来自多种输入源(文本、PDF、图像、音频及其他数据格式)信息的能力。
Google 的 Gemini AI 模型通过理解并整合文本、代码、音频、图像和视频来支持这一能力。
Java AI 的 Message 接口通过引入 Media 类型来支持多模态 AI 模型。该类型包含消息中媒体附件的数据及其信息,使用 Spring 的 org.springframework.util.MimeType 和 java.lang.Object 来承载原始媒体数据。
以下是一个简单代码示例,摘自 GoogleGenAiChatModelIT.java,演示文本与图像组合:
byte[] data = new ClassPathResource("/vertex-test.png").getContentAsByteArray(); // 读取图片字节
var userMessage = UserMessage.builder()
.text("Explain what do you see o this picture?") // 提示词:解释你在这张图里看到什么
.media(List.of(new Media(MimeTypeUtils.IMAGE_PNG, data))) // 附加 PNG 图片
.build();
ChatResponse response = chatModel.call(new Prompt(List.of(this.userMessage)));PDF(PDF 文档)
Google GenAI 支持 PDF 输入类型。使用 application/pdf 媒体类型把 PDF 文件附加到消息上:
var pdfData = new ClassPathResource("/spring-ai-reference-overview.pdf"); // 读取 PDF 资源
var userMessage = UserMessage.builder()
.text("You are a very professional document summarization specialist. Please summarize the given document.")
// 提示词:你是一位非常专业的文档摘要专家。请总结给定文档。
.media(List.of(new Media(new MimeType("application", "pdf"), pdfData))) // 附加 PDF
.build();
var response = this.chatModel.call(new Prompt(List.of(userMessage)));Cached Content(缓存内容)
Google GenAI 的 Context Caching(上下文缓存)允许你缓存大量内容(如长文档、代码仓库或媒体),并在多次请求间复用。这会显著降低 API 成本,并改善对同一内容重复查询的响应延迟。
Benefits(优势)
- 降低成本:缓存 token 的计费费率远低于普通输入 token(通常便宜 75-90%)。
- 提升性能:复用缓存内容可减少大上下文的处理时间。
- 一致性:相同的缓存上下文能保证多次请求间的响应一致。
Cache Requirements(缓存要求)
- 最小缓存大小:32,768 个 token(约 25,000 词)。
- 最大缓存时长:默认 1 小时(可通过 TTL 配置)。
- 缓存内容必须包含 system instructions(系统指令)或对话历史。
Using Cached Content Service(使用缓存内容服务)
Java AI 提供了 GoogleGenAiCachedContentService 用于编程式缓存管理。使用 Spring Boot 自动配置时该服务会自动配置。
@Autowired
private GoogleGenAiCachedContentService cachedContentService;
String largeDocument = "... your large context here (>32k tokens) ...";
CachedContentRequest request = CachedContentRequest.builder()
.model("gemini-2.5-flash")
.contents(List.of(
Content.builder()
.role("user")
.parts(List.of(Part.fromText(largeDocument))) // 文本内容作为 part
.build()
))
.displayName("My Large Document Cache") // 显示名称,便于识别
.ttl(Duration.ofHours(1)) // 缓存存活 1 小时
.build();
GoogleGenAiCachedContent cachedContent = cachedContentService.create(request);
String cacheName = cachedContent.getName(); // 保存这个名字以便复用Auto-Caching(自动缓存)
Java AI 可以在大 prompt 超过指定 token 阈值时自动缓存它们:
# 自动缓存超过 100,000 token 的 prompt
spring.ai.google.genai.chat.auto-cache-threshold=100000
# 自动缓存 TTL 设为 1 小时
spring.ai.google.genai.chat.auto-cache-ttl=PT1HSample Controller(示例控制器)
新建一个 Spring Boot 项目,把 spring-ai-starter-model-google-genai 加入 pom(或 gradle)依赖。
在 src/main/resources 目录下添加 application.properties 文件,用于启用并配置 Google GenAI 聊天模型:
使用 Gemini Developer API(API key)
spring.ai.google.genai.api-key=YOUR_API_KEY # 你的 API key
spring.ai.google.genai.chat.model=gemini-2.5-flash # 使用 gemini-2.5-flash 模型
spring.ai.google.genai.chat.temperature=0.5 # 温度设为 0.5使用 Vertex AI
spring.ai.google.genai.project-id=PROJECT_ID # 你的 GCP 项目 ID
spring.ai.google.genai.location=LOCATION # GCP 区域
spring.ai.google.genai.chat.model=gemini-2.5-flash # 使用 gemini-2.5-flash 模型
spring.ai.google.genai.chat.temperature=0.5 # 温度设为 0.5把 project-id 换成你的 Google Cloud 项目 ID,location 是 Google Cloud 区域,如 us-central1、europe-west1 等。
每个模型都有各自支持的区域,可在模型页面查看支持区域列表。
这会创建一个 GoogleGenAiChatModel 实现,你可以注入到自己的类中。下面是一个简单的 @Controller 类示例,用聊天模型做文本生成:
@RestController
public class ChatController {
private final GoogleGenAiChatModel chatModel;
@Autowired
public ChatController(GoogleGenAiChatModel chatModel) {
this.chatModel = chatModel;
}
@GetMapping("/ai/generate")
public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
// 默认消息:给我讲个笑话
return Map.of("generation", this.chatModel.call(message));
}
@GetMapping("/ai/generateStream")
public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
// 流式接口,逐块返回响应
Prompt prompt = new Prompt(new UserMessage(message));
return this.chatModel.stream(prompt);
}
}Manual Configuration(手动配置)
GoogleGenAiChatModel 实现了 ChatModel,并使用 com.google.genai.Client 连接 Google GenAI 服务。
在项目的 Maven pom.xml 中添加 spring-ai-google-genai 依赖:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-google-genai</artifactId>
</dependency>或添加到 Gradle build.gradle:
dependencies {
implementation 'org.springframework.ai:spring-ai-google-genai'
}请参考 Dependency Management(依赖管理)一节,把 Java AI BOM 加入构建文件。
接下来创建 GoogleGenAiChatModel 并用它做文本生成:
使用 API key
Client genAiClient = Client.builder()
.apiKey(System.getenv("GOOGLE_API_KEY")) // 从环境变量读 API key
.build();
var chatModel = new GoogleGenAiChatModel(genAiClient,
GoogleGenAiChatOptions.builder()
.model(ChatModel.GEMINI_2_0_FLASH) // 使用 Gemini 2.0 Flash
.temperature(0.4) // 温度 0.4
.build());
ChatResponse response = this.chatModel.call(
new Prompt("Generate the names of 5 famous pirates.")); // 生成 5 个著名海盗的名字使用 Vertex AI
Client genAiClient = Client.builder()
.project(System.getenv("GOOGLE_CLOUD_PROJECT")) // 从环境变量读 GCP 项目
.location(System.getenv("GOOGLE_CLOUD_LOCATION")) // 从环境变量读 GCP 区域
.vertexAI(true) // 启用 Vertex AI 模式
.build();
var chatModel = new GoogleGenAiChatModel(genAiClient,
GoogleGenAiChatOptions.builder()
.model(ChatModel.GEMINI_2_0_FLASH) // 使用 Gemini 2.0 Flash
.temperature(0.4) // 温度 0.4
.build());
ChatResponse response = this.chatModel.call(
new Prompt("Generate the names of 5 famous pirates.")); // 生成 5 个著名海盗的名字Migration from Vertex AI Gemini(从 Vertex AI Gemini 迁移)
如果你之前用的是 Vertex AI Gemini 实现(spring-ai-vertex-ai-gemini,已被移除),请迁移到 Google GenAI:
关键差异:
- SDK:Google GenAI 使用新的
com.google.genai.Client,而不是com.google.cloud.vertexai.VertexAI。 - 认证:同时支持 API key 和 Google Cloud 凭据(Vertex AI 模式)。
- 包名:类位于
org.springframework.ai.google.genai,而不是org.springframework.ai.vertexai.gemini。 - 属性前缀:使用
spring.ai.google.genai,而不是spring.ai.vertex.ai.gemini。
Groq Chat
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/groq-chat.html 📌 原文版本:Java AI 2.0.1
白话解读
Groq 是一家以超快推理速度出名的 AI 服务商(LPU 芯片)。Java AI 没有给 Groq 写独立的客户端,而是直接复用 OpenAI 的客户端,把 base-url 指向 Groq 的接口即可——因为 Groq 的 API 跟 OpenAI 完全兼容。
1. 简介
Groq 是一家提供超低延迟大模型推理服务的厂商。它走的接口协议和 OpenAI Chat Completion API 完全一致,所以 Java AI 让 OpenAI Chat Client 直接兼容 Groq。你只需要在配置里把 base-url 换成 Groq 的地址,把 api-key 换成 Groq 的 key 就行了,不用引入新的 starter。
2. 准备工作
- 到 https://console.groq.com/ 注册账号并生成一个 API Key。
- 在 Spring Boot 项目里引入
spring-ai-starter-model-openai依赖(OpenAI 客户端)。 - 在
application.yml或application.properties里配置 Groq 的连接信息。
3. 核心配置
3.1 Maven 依赖
<!-- 引入 OpenAI starter,复用它来访问 Groq -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>3.2 应用配置(application.yml)
spring:
ai:
openai:
# 关键点:把 base-url 指向 Groq 的 OpenAI 兼容接口
base-url: https://api.groq.com/openai
api-key: ${GROQ_API_KEY} # 你的 Groq API Key
chat:
# 选一个 Groq 支持的模型,例如 llama-3.3-70b-versatile
options:
model: llama-3.3-70b-versatile
temperature: 0.7小提示
Groq 的 base-url 末尾必须带 /openai,这是它专门为兼容 OpenAI 协议暴露的网关。
3.3 应用配置(application.properties)
spring.ai.openai.base-url=https://api.groq.com/openai
spring.ai.openai.api-key=${GROQ_API_KEY}
spring.ai.openai.chat.options.model=llama-3.3-70b-versatile
spring.ai.openai.chat.options.temperature=0.74. 代码调用示例
把 ChatClient 注入到 Bean 里就能直接调用,跟使用 OpenAI 完全一样:
// 注入 Spring AI 自动配置好的 ChatClient
@RestController
class GroqChatController {
private final ChatClient chatClient;
// 由 Spring AI 自动装配,底层走 OpenAI 客户端 + Groq base-url
GroqChatController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping("/ask")
String ask(@RequestParam String question) {
// 调用 Groq 上托管的 Llama 3.3 模型
return chatClient.prompt(question)
.call()
.content(); // 直接拿到字符串回复
}
}5. 流式输出
Groq 最大的卖点就是快,所以一般会用流式输出来进一步压低首 token 延迟:
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
Flux<String> stream(@RequestParam String question) {
return chatClient.prompt(question)
.stream() // 走流式接口
.content(); // 返回 Flux<String>,每个 token 推一次
}6. 常用模型一览
| 模型 ID | 说明 |
|---|---|
llama-3.3-70b-versatile | Llama 3.3 70B,质量好,速度极快 |
llama-3.1-8b-instant | Llama 3.1 8B,极速版,延迟最低 |
mixtral-8x7b-32768 | Mixtral MoE,长上下文 |
whisper-large-v3 | 语音转文字(Groq 也托管 Whisper) |
白话解读
模型列表以 Groq 官网为准(https://console.groq.com/docs/models),因为 Groq 经常上新模型。
7. 运行时动态切换模型
因为底座是 OpenAI 客户端,你可以用 OpenAiChatOptions 在运行时切模型:
ChatResponse response = chatClient.prompt("用一句话讲个笑话")
.options(OpenAiChatOptions.builder()
.model("llama-3.1-8b-instant") // 临时切换为更快的模型
.temperature(0.9)
.build())
.call()
.chatResponse();8. 注意事项
注意
- Groq 提供的是推理托管服务,模型本身的训练数据、上下文窗口都受限于上游(Meta、Mistral 等)。
- 免费额度有限,生产环境请关注 https://console.groq.com/settings/limits 的配额。
- 如果只想用 Groq 的语音转文字(Whisper),可以结合
spring-ai-openai-speech-transcriptionstarter,把base-url同样指向 Groq。
9. 小结
Groq 在 Java AI 里的接入非常"轻"——复用 OpenAI 客户端 + 改 base-url + 配 api-key,三步搞定。它的价值在于超低延迟,特别适合对响应速度敏感的场景(实时陪聊、代码补全、语音助手)。
Mistral AI Chat
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/mistralai-chat.html 📌 原文版本:Java AI 2.0.1
白话解读
Mistral AI 是一家法国的大模型公司,模型质量好、参数效率高。Java AI 提供独立的 Mistral 客户端(不像 Groq 那样借用 OpenAI),完整支持结构化输出、推理模式、多模态等功能。
1. 简介
Mistral AI 提供多种商用和开源大模型,包括:
- Mistral Large:旗舰模型,对标 GPT-4 / Claude
- Mistral Small:性价比款,速度快
- Codestral:代码专用模型
- Pixtral:多模态模型(支持图片)
- Ministral / Mixtral:轻量级和 MoE 架构
Java AI 给 Mistral 写了一个独立的 starter,所以你可以享受到 Mistral 平台的专有能力,比如:
- 结构化输出(JSON Schema)
- Reasoning Mode(推理模式)
- 多模态(Pixtral)
- 安全/审核(Moderation)
2. 准备工作
- 到 https://console.mistral.ai/ 注册并生成 API Key。
- 在项目里引入 Mistral 专用的 starter(不是 OpenAI starter)。
- 在配置文件里设置 Mistral 的连接信息。
3. 核心配置
3.1 Maven 依赖
<!-- 引入 Mistral AI 专用 starter -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-mistral-ai</artifactId>
</dependency>3.2 应用配置
spring:
ai:
mistralai:
api-key: ${MISTRAL_API_KEY} # 你的 Mistral API Key
chat:
options:
model: mistral-large-latest # 默认模型
temperature: 0.7
max-tokens: 1024properties 写法:
spring.ai.mistralai.api-key=${MISTRAL_API_KEY}
spring.ai.mistralai.chat.options.model=mistral-large-latest
spring.ai.mistralai.chat.options.temperature=0.74. 基本调用
@RestController
class MistralController {
private final ChatClient chatClient;
MistralController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping("/ask")
String ask(@RequestParam String question) {
// 走默认配置的 Mistral Large 模型
return chatClient.prompt(question).call().content();
}
}5. 结构化输出
Mistral 原生支持 JSON Schema 结构化输出,所以可以放心使用 .entity():
record Person(String name, int age, List<String> hobbies) {}
Person person = chatClient.prompt()
.user("给我虚构一个人物,包含姓名、年龄和3个爱好")
.call()
.entity(Person.class); // 自动反序列化为 Person 对象
System.out.println(person.name()); // 比如 "李逍遥"
System.out.println(person.hobbies()); // ["行侠仗义", "品茶", "下棋"]6. 推理模式(Reasoning)
Mistral 部分模型支持"推理模式",会先把思考过程打出来,再给最终答案:
ChatResponse response = chatClient.prompt()
.options(MistralAiChatOptions.builder()
.model("magistral-medium-latest") // 支持 reasoning 的模型
.build())
.user("9.11 和 9.9 哪个更大?")
.call()
.chatResponse();
// Mistral 的推理模式会把思考过程放进 ChatResponse 的 reasoning 字段
String reasoning = response.getResult().getMetadata().getReasoning();
String finalAnswer = response.getResult().getOutput().getContent();小提示
不同 Mistral 模型的推理能力不一样,要选 magistral-medium-latest 这种专门支持 reasoning 的模型。
7. 多模态(Pixtral)
Mistral 的 pixtral-12b-2409 是支持图片输入的模型:
// 把图片作为 UserMessage 的 media 字段传进去
UserMessage userMessage = new UserMessage(
"请描述这张图片的内容",
new Media(MimeTypeUtils.IMAGE_PNG, new URL("https://example.com/cat.png")));
String answer = chatClient.prompt()
.messages(userMessage)
.options(MistralAiChatOptions.builder()
.model("pixtral-12b-2409")
.build())
.call()
.content();8. 流式输出
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
Flux<String> stream(@RequestParam String question) {
return chatClient.prompt(question)
.stream()
.content();
}9. 常用模型一览
| 模型 ID | 能力 |
|---|---|
mistral-large-latest | 旗舰,最强综合能力 |
mistral-small-latest | 性价比 |
codestral-latest | 代码生成 |
pixtral-12b-2409 | 多模态(图片) |
magistral-medium-latest | 推理模式 |
ministral-8b-latest | 轻量级 |
mixtral-8x7b-instruct | MoE 架构 |
10. 注意事项
注意
- Mistral 部分模型(如
pixtral、magistral)需要在 API 控制台确认你的账号有权访问。 - 不同模型的最大上下文长度(
maxTokens)不一样,可在 https://docs.mistral.ai/getting-started/models/models_overview/ 查看。 - Mistral 在欧洲合规性做得很好,对 GDPR 严格的场景特别合适。
11. 小结
Mistral AI 在 Java AI 里走的是独立 starter,功能完整,支持结构化输出、推理模式、多模态。如果你看重模型质量和欧洲合规,Mistral 是 OpenAI 之外的优秀备选。
MiniMax Chat
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/minimax-chat.html 📌 原文版本:Java AI 2.0.1
白话解读
MiniMax 提供了兼容 Anthropic Claude 协议的接口(OpenAI 兼容、MiniMax Anthropic 兼容等多种),所以 Java AI 没有给它单独写 starter,直接复用 Anthropic 客户端,把 base-url 指向 MiniMax 的 Anthropic 兼容地址即可。
1. 简介
MiniMax 是国内一家提供大模型推理服务的厂商,旗下 MiniMax、MiniMax-M1、MiniMax-VL 等模型因为长上下文、价格友好被广泛使用。它提供了多种 API 协议入口,其中:
- Anthropic 兼容协议:走
/anthropic路径,跟 Claude 的 API 协议完全一致。
Java AI 没有为 MiniMax 单独写 starter,因为复用 Anthropic 客户端是最省事的方案——只要把 base-url 指向 https://api.minimax.chat/anthropic 就搞定了。
2. 接入步骤
2.1 Maven 依赖
<!-- 复用 Anthropic starter -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-anthropic</artifactId>
</dependency>2.2 应用配置
spring:
ai:
anthropic:
# 关键:把 base-url 指向 MiniMax 的 Anthropic 兼容地址
base-url: https://api.minimax.chat/anthropic
api-key: ${MiniMax_API_KEY} # 你的 MiniMax API Key
chat:
options:
model: MiniMax
max-tokens: 8192properties 写法:
spring.ai.anthropic.base-url=https://api.minimax.chat/anthropic
spring.ai.anthropic.api-key=${MiniMax_API_KEY}
spring.ai.anthropic.chat.options.model=MiniMax
spring.ai.anthropic.chat.options.max-tokens=8192白话解读
之所以用 Anthropic 客户端,而不是 OpenAI 客户端,是因为 MiniMax 的 Anthropic 兼容接口稳定性更好,并且支持 Claude 的 Extended Thinking、Tool Use 等高级特性。
3. 调用示例
@RestController
class MiniMaxController {
private final ChatClient chatClient;
MiniMaxController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping("/ask")
String ask(@RequestParam String question) {
// 底层是 Anthropic 客户端,请求打到 api.minimax.chat
return chatClient.prompt(question).call().content();
}
}4. 注意事项
注意
- 这个页面在 Java AI 官方文档中特别简短,因为确实就只是"换 base-url"这一件事。
- MiniMax 的 Anthropic 兼容接口并不是 100% 等同于 Claude,偶尔会有细微差异(比如某些 beta feature 不支持)。
- 模型 ID 列表请到 https://platform.minimax.chat/docs/api-reference/ 查阅最新可用模型。
5. 小结
MiniMax 的接入方式是 Anthropic 客户端 + 换 base-url,非常简洁。如果你已经在用 Java AI 的 Anthropic 客户端,迁移到 MiniMax 几乎是零成本——改一行配置即可。
NVIDIA Chat
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/nvidia-chat.html 📌 原文版本:Java AI 2.0.1
白话解读
NVIDIA NIM(NVIDIA Inference Microservice)把自家和各家的开源模型打包成 OpenAI 兼容的 API 暴露出来。Java AI 通过 OpenAI 客户端 + 改 base-url 就能访问 NVIDIA NIM,跑本地或云端的 NVIDIA 加速模型。
1. 简介
NVIDIA NIM 是 NVIDIA 推出的一套模型推理服务,可以:
- 本地部署:用 NVIDIA 显卡跑开源模型(Llama、Mistral、Phi 等)
- 云端调用:用 NVIDIA 托管的 API(build.nvidia.com)
无论哪种部署方式,NVIDIA NIM 都暴露 OpenAI 兼容的 /v1/chat/completions 接口,所以 Java AI 用 OpenAI 客户端就能直接连。
2. 准备工作
方案 A:使用 NVIDIA 托管 API(build.nvidia.com)
- 到 https://build.nvidia.com/ 注册并生成 API Key。
- 直接使用 NVIDIA 提供的云端 endpoint。
方案 B:本地部署 NVIDIA NIM
- 安装 NVIDIA NIM 容器(需要 NVIDIA 显卡 + Docker + NGC 账号)。
- 启动容器后,会暴露本地
http://localhost:8000/v1接口。 - 用这个本地地址作为 base-url。
3. 核心配置
3.1 Maven 依赖
<!-- 复用 OpenAI starter -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>3.2 应用配置(云端 API)
spring:
ai:
openai:
# NVIDIA 托管 API 的 endpoint
base-url: https://integrate.api.nvidia.com/v1
api-key: ${NVIDIA_API_KEY}
chat:
options:
model: meta/llama-3.1-70b-instruct # NVIDIA 上托管的模型 ID
temperature: 0.5
max-tokens: 10243.3 应用配置(本地 NIM)
spring:
ai:
openai:
# 本地 NIM 容器暴露的地址(默认 8000 端口)
base-url: http://localhost:8000/v1
api-key: not-required # 本地 NIM 一般不需要 key,写个占位
chat:
options:
model: meta/llama-3.1-8b-instruct
max-tokens: 1024properties 写法:
spring.ai.openai.base-url=https://integrate.api.nvidia.com/v1
spring.ai.openai.api-key=${NVIDIA_API_KEY}
spring.ai.openai.chat.options.model=meta/llama-3.1-70b-instruct
spring.ai.openai.chat.options.max-tokens=1024注意
NVIDIA NIM 的 API 强制要求传 max_tokens,不传会报错。请一定在 options 里配置。
4. 基本调用
@RestController
class NvidiaChatController {
private final ChatClient chatClient;
NvidiaChatController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping("/ask")
String ask(@RequestParam String question) {
return chatClient.prompt(question).call().content();
}
}5. 流式输出
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
Flux<String> stream(@RequestParam String question) {
return chatClient.prompt(question).stream().content();
}6. 常用模型
NVIDIA NIM 上托管的模型列表经常更新,常见的有:
| 模型 ID | 说明 |
|---|---|
meta/llama-3.1-70b-instruct | Llama 3.1 70B |
meta/llama-3.1-8b-instruct | Llama 3.1 8B(更快) |
meta/llama-3.2-90b-vision-instruct | Llama 3.2 90B 多模态 |
mistralai/mistral-large-2-instruct | Mistral Large 2 |
microsoft/phi-3-medium-128k-instruct | Phi-3 Medium |
白话解读
NVIDIA 上线模型很快,ID 经常变化。最新列表请到 https://build.nvidia.com/explore/discover 看。
7. 注意事项
注意
- NVIDIA NIM 强制要求传
max_tokens,否则接口直接报错。 - 云端 API 的免费额度有限,生产环境请关注 https://build.nvidia.com/ 的配额。
- 本地部署需要 NVIDIA GPU + 安装 NVIDIA Container Toolkit。
- 模型 ID 的命名规则是
<厂商>/<模型名>,中间是斜杠,不是 OpenAI 那种纯模型名。
8. 小结
NVIDIA Chat 借助 OpenAI 客户端 + NIM 服务,把 NVIDIA 显卡的算力优势带到了 Java AI 项目里。云端 API 适合快速验证,本地 NIM 适合数据敏感 / 大批量推理。无论哪种方式,配置都很简单,关键就一个 base-url。
Ollama Chat
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/ollama-chat.html 📌 原文版本:Java AI 2.0.1
白话解读
Ollama 是本地跑开源大模型的瑞士军刀,支持 Llama、Qwen、Mistral、DeepSeek 等几乎所有主流模型。Java AI 给它写了独立 starter,比 OpenAI 兼容模式功能更完整(思考模式、JSON Schema、自动拉取模型、多模态)。
1. 简介
Ollama 是一个本地大模型运行框架,让你可以一行命令把模型跑起来:
ollama pull llama3.2 # 拉取模型
ollama run llama3.2 # 命令行对话Ollama 默认监听 http://localhost:11434,对外暴露 REST API。Java AI 提供 OllamaChatModel 与之对接。
小提示
Ollama 同时也提供 OpenAI 兼容端点(http://localhost:11434/v1),如果你不想引入 Ollama 专用 starter,可以直接用 OpenAI starter 连过去。详见「OpenAI API 兼容性」一节。
2. 准备工作
方式 A:本地安装
- 到 https://ollama.com/download 下载安装 Ollama。
- 拉取你需要的模型:
ollama pull <model-name>。 - Ollama 服务会自动启动,监听 11434 端口。
方式 B:Testcontainers 自动启动
Java AI 测试支持 Testcontainers,集成测试时会自动拉起一个 Ollama 容器。
拉取模型的几种方式
# 官方模型库
ollama pull llama3.2
ollama pull qwen2.5
ollama pull deepseek-r1
# Hugging Face GGUF 模型
ollama pull hf.co/<username>/<model-repository>3. 核心配置
3.1 Maven 依赖
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
</dependency>3.2 基础属性
| 属性 | 描述 | 默认值 |
|---|---|---|
spring.ai.ollama.base-url | Ollama API 地址 | http://localhost:11434 |
spring.ai.ollama.init.pull-model-strategy | 启动时拉取模型策略 | never |
spring.ai.ollama.init.timeout | 拉取模型超时时间 | 5m |
spring.ai.ollama.init.max-retries | 拉取模型重试次数 | 0 |
spring.ai.ollama.init.chat.include | 是否初始化聊天模型 | true |
spring.ai.ollama.init.chat.additional-models | 额外初始化的模型列表 | [] |
3.3 启用开关(多模型配置)
spring:
ai:
model:
chat: ollama # 启用 Ollama(默认)
# chat: none # 禁用 Ollama3.4 聊天属性
| 属性 | 描述 | 默认值 |
|---|---|---|
spring.ai.ollama.chat.model | 使用的模型名 | mistral |
spring.ai.ollama.chat.format | 输出格式("json" 或 JSON Schema 字符串) | - |
spring.ai.ollama.chat.keep_alive | 模型在内存中保持加载的时长 | 5m |
spring.ai.ollama.chat.think | 是否启用思考模式(推理模型专用) | - |
spring.ai.ollama.chat.temperature | 温度参数 | 0.8 |
spring.ai.ollama.chat.num-ctx | 上下文窗口大小 | 2048 |
spring.ai.ollama.chat.num-gpu | 发送到 GPU 的层数(macOS 默认为 1) | -1 |
spring.ai.ollama.chat.top-k | top-k 采样 | 40 |
spring.ai.ollama.chat.top-p | top-p 采样 | 0.9 |
spring.ai.ollama.chat.seed | 随机种子 | -1 |
spring.ai.ollama.chat.stop | 停止序列 | - |
spring.ai.ollama.chat.tool-callbacks | 工具回调 | - |
4. 自动拉取模型
Ollama 启动时可以自动拉取模型。三种策略:
always:总是拉取(保证最新版本)when_missing:只在缺失时拉取never:从不自动拉取
spring:
ai:
ollama:
init:
pull-model-strategy: always
timeout: 60s
max-retries: 1
chat:
additional-models: # 额外要加载的模型
- llama3.2
- qwen2.5注意
模型拉取会拖慢启动时间,生产环境请预下载模型,不要开启 always。
5. 运行时选项
用 OllamaChatOptions 可以在运行时覆盖模型配置:
ChatResponse response = chatModel.call(
new Prompt("列几个著名海盗的名字",
OllamaChatOptions.builder()
.model(OllamaModel.LLAMA3_1) // 临时指定模型
.temperature(0.4)
.build()));6. 工具调用
OllamaChatModel 支持工具调用,但需要 Ollama 0.2.8+,流式模式需要 0.4.6+。
@Bean
ToolCallback weatherTool() {
return FunctionToolCallback.builder("get_weather", new WeatherService())
.description("查询天气")
.build();
}工具会自动被 ChatClient 通过 ToolCallingAdvisor 注入。
7. 思考模式(推理)
Ollama 0.12+ 对具备思考能力的模型(qwen3:*-thinking、deepseek-r1、deepseek-v3.1、gpt-oss)默认自动启用思考。
// 布尔开关(Qwen3、DeepSeek 系列)
ChatResponse response = chatModel.call(
new Prompt("strawberry 里有多少个字母 r?",
OllamaChatOptions.builder()
.model("qwen3")
.enableThinking()
.build()));
// 推理内容放在 metadata 里
String thinking = response.getResult().getMetadata().get("thinking");
String answer = response.getResult().getOutput().getText();GPT-OSS 模型需要"思考级别":
OllamaChatOptions.builder()
.model("gpt-oss")
.thinkLow() // 低强度思考
.thinkMedium() // 中强度
.thinkHigh(); // 高强度流式思考示例:
Flux<ChatResponse> stream = chatModel.stream(
new Prompt("解释量子纠缠",
OllamaChatOptions.builder()
.model("qwen3")
.enableThinking()
.build()));
stream.subscribe(r -> {
String thinking = r.getResult().getMetadata().get("thinking");
String content = r.getResult().getOutput().getText();
if (thinking != null && !thinking.isEmpty()) {
System.out.println("[Thinking] " + thinking);
}
if (content != null && !content.isEmpty()) {
System.out.println("[Answer] " + content);
}
});8. 多模态
Ollama 的 LLaVA / BakLLaVA 等模型支持图像输入。Java AI 通过 Media 类型传递图片:
// 把图片打包成 UserMessage
var imageResource = new ClassPathResource("/multimodal.test.png");
var userMessage = new UserMessage("描述这张图片",
new Media(MimeTypeUtils.IMAGE_PNG, imageResource));
ChatResponse response = chatModel.call(new Prompt(userMessage,
OllamaChatOptions.builder()
.model(OllamaModel.LLAVA)
.build()));9. 结构化输出
Ollama 提供两种结构化输出模式:
9.1 简单 JSON 模式(任意结构)
ChatResponse response = chatModel.call(
new Prompt("列出 3 个欧洲国家",
OllamaChatOptions.builder()
.model("llama3.2")
.format("json") // 任意 JSON 结构
.build()));9.2 JSON Schema 模式(强制结构)
String jsonSchema = """
{
"type": "object",
"properties": {
"countries": {
"type": "array",
"items": { "type": "string" }
}
},
"required": ["countries"]
}
""";
ChatResponse response = chatModel.call(
new Prompt("列出 3 个欧洲国家",
OllamaChatOptions.builder()
.model("llama3.2")
.outputSchema(jsonSchema) // 强制 schema
.build()));模型必须返回 {"countries": ["France", "Germany", "Italy"]} 这种结构。
9.3 与 BeanOutputConverter 集成
record MathReasoning(
@JsonProperty(required = true, value = "steps") Steps steps,
@JsonProperty(required = true, value = "final_answer") String finalAnswer) {
record Steps(
@JsonProperty(required = true, value = "items") Items[] items) {
record Items(
@JsonProperty(required = true, value = "explanation") String explanation,
@JsonProperty(required = true, value = "output") String output) {}
}
}
var converter = new BeanOutputConverter<>(MathReasoning.class);
Prompt prompt = new Prompt("解方程 8x + 7 = -23",
OllamaChatOptions.builder()
.model(OllamaModel.LLAMA3_2.getName())
.outputSchema(converter.getJsonSchema()) // 用 record 自动生成 schema
.build());
ChatResponse response = chatModel.call(prompt);
MathReasoning result = converter.convert(response.getResult().getOutput().getText());10. OpenAI API 兼容性
Ollama 兼容 OpenAI 协议,可以直接用 Java AI OpenAI 客户端访问:
spring:
ai:
openai:
base-url: http://localhost:11434/v1
api-key: ollama # 占位符
chat:
model: mistral通过 extraBody 传递 Ollama 特有参数:
OpenAiChatOptions options = OpenAiChatOptions.builder()
.model("llama3.2")
.extraBody(Map.of(
"num_predict", 100,
"top_k", 40,
"repeat_penalty", 1.1))
.build();OpenAI 兼容端的思考模式
Ollama 的 OpenAI 兼容端点把推理内容放在 reasoning_content 字段:
@Configuration
class OllamaConfig {
@Bean
OpenAiChatModel ollamaChatModel() {
return OpenAiChatModel.builder()
.options(OpenAiChatOptions.builder()
.baseUrl("http://localhost:11434/v1")
.apiKey("ollama")
.model("deepseek-r1")
.build())
.build();
}
}
ChatResponse response = chatModel.call(
new Prompt("strawberry 里有多少个字母 r?"));
String reasoning = response.getResult().getMetadata().get("reasoningContent");
String answer = response.getResult().getOutput().getText();11. Hugging Face 模型
Ollama 可以直接拉取 GGUF 格式的 HuggingFace 模型:
spring.ai.ollama.chat.model=hf.co/bartowski/gemma-2-2b-it-GGUF
spring.ai.ollama.init.pull-model-strategy=always12. 示例控制器
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
options:
model: mistral
temperature: 0.7@RestController
public class ChatController {
private final OllamaChatModel chatModel;
public ChatController(OllamaChatModel chatModel) {
this.chatModel = chatModel;
}
@GetMapping("/ai/generate")
public Map<String, String> generate(
@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return Map.of("generation", this.chatModel.call(message));
}
@GetMapping("/ai/generateStream")
public Flux<ChatResponse> generateStream(
@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
Prompt prompt = new Prompt(new UserMessage(message));
return this.chatModel.stream(prompt);
}
}13. 手动配置(不用 starter)
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama</artifactId>
</dependency>var ollamaApi = OllamaApi.builder().build();
var chatModel = OllamaChatModel.builder()
.ollamaApi(ollamaApi)
.options(OllamaChatOptions.builder()
.model(OllamaModel.MISTRAL)
.temperature(0.9)
.build())
.build();
ChatResponse response = chatModel.call(
new Prompt("Generate the names of 5 famous pirates."));
// 或者流式
Flux<ChatResponse> stream = chatModel.stream(
new Prompt("Generate the names of 5 famous pirates."));14. 小结
Ollama 是 Java AI 中唯一支持大量开源模型本地运行的方案。它提供了:
- 本地 + 免费:跑开源模型不要钱
- 思考模式 / JSON Schema / 多模态:能力完整
- 自动拉取模型:开发体验好
- OpenAI 兼容端点:既能享受 Ollama 专属能力,又能复用 OpenAI 客户端
如果你要私有化部署、对数据敏感,Ollama 是最值得考虑的方案。
Perplexity Chat
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/perplexity-chat.html 📌 原文版本:Java AI 2.0.1
白话解读
Perplexity 是"自带联网搜索"的大模型服务,回答问题时会附带实时检索结果。Java AI 没有给它写独立 starter,而是复用 OpenAI 客户端,把 base-url 指向 https://api.perplexity.ai 即可。
1. 简介
Perplexity AI 把语言模型与实时联网搜索结合在一起,回答问题时不仅生成文字,还会自动去网上查最新资料。Java AI 通过 OpenAI 客户端访问它,因为 Perplexity 提供了 OpenAI 兼容的 API。
注意
Perplexity API 与 OpenAI 不完全兼容:
- 不支持 tool calling(搜索结果直接整合进回复)
- 不支持多模态(不能传图片、音频)
- 不支持 embedding(所以接入时要把 embedding 模型禁用)
2. 准备工作
- 到 https://www.perplexity.ai/settings/api 创建 API Key。
- 在 Spring Boot 项目里引入 OpenAI starter。
- 配置 base-url 为
https://api.perplexity.ai。
3. 核心配置
3.1 Maven 依赖
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>3.2 应用配置
properties 写法:
spring.ai.openai.api-key=<your-perplexity-api-key>
spring.ai.openai.base-url=https://api.perplexity.ai
spring.ai.openai.chat.model=llama-3.1-sonar-small-128k-onlineyaml 写法(推荐):
spring:
ai:
openai:
api-key: ${PERPLEXITY_API_KEY}
base-url: ${PERPLEXITY_BASE_URL}
chat:
model: ${PERPLEXITY_MODEL}.env 文件:
export PERPLEXITY_API_KEY=<your-perplexity-api-key>
export PERPLEXITY_BASE_URL=https://api.perplexity.ai
export PERPLEXITY_MODEL=llama-3.1-sonar-small-128k-online3.3 关闭 embedding 模型
Perplexity 不提供 embedding 服务,必须禁用:
spring.ai.model.embedding=none4. 聊天属性
4.1 重试属性(继承自 OpenAI)
| 属性 | 描述 | 默认值 |
|---|---|---|
spring.ai.retry.max-attempts | 最大重试次数 | 10 |
spring.ai.retry.backoff.initial-interval | 指数退避初始间隔 | 2 sec |
spring.ai.retry.backoff.multiplier | 退避乘数 | 5 |
spring.ai.retry.backoff.max-interval | 最大退避时长 | 3 min |
spring.ai.retry.on-client-errors | 4xx 错误是否重试 | false |
spring.ai.retry.exclude-on-http-codes | 不重试的 HTTP 状态码 | empty |
spring.ai.retry.on-http-codes | 触发重试的 HTTP 状态码 | empty |
4.2 连接属性
| 属性 | 描述 | 默认值 |
|---|---|---|
spring.ai.openai.base-url | 必须设为 https://api.perplexity.ai | - |
spring.ai.openai.chat.api-key | Perplexity API Key | - |
4.3 模型配置
| 属性 | 描述 | 默认值 |
|---|---|---|
spring.ai.openai.chat.model | 模型名 | - |
spring.ai.openai.chat.temperature | 温度(0~2) | 0.2 |
spring.ai.openai.chat.frequency-penalty | 频率惩罚(>0,与 presence_penalty 互斥) | 1 |
spring.ai.openai.chat.max-tokens | 最大生成 token 数 | - |
spring.ai.openai.chat.presence-penalty | 存在惩罚(-2~2) | 0 |
spring.ai.openai.chat.top-p | 核采样阈值(0~1) | 0.9 |
spring.ai.openai.chat.stream-usage | 流式最后是否带 usage chunk | false |
5. 运行时选项
ChatResponse response = chatModel.call(
new Prompt("讲一个关于春天的短故事",
OpenAiChatOptions.builder()
.model("llama-3.1-sonar-small-128k-online")
.temperature(0.4)
.build()));6. 工具调用
注意
Perplexity 不支持显式 tool calling。它会把搜索结果直接整合进响应,而不是通过 tool_calls 字段返回。如果你的应用依赖 Java AI 的工具调用框架,请选其他厂商。
7. 多模态
注意
Perplexity API 目前不支持媒体内容(图片、音频都不行)。
8. 示例控制器
spring.ai.openai.api-key=${PERPLEXITY_API_KEY}
spring.ai.openai.base-url=https://api.perplexity.ai
spring.ai.openai.chat.model=llama-3.1-sonar-small-128k-online
spring.ai.openai.chat.temperature=0.7
# Perplexity 不支持 embedding,必须禁用
spring.ai.model.embedding=none@RestController
public class ChatController {
private final OpenAiChatModel chatModel;
@Autowired
public ChatController(OpenAiChatModel chatModel) {
this.chatModel = chatModel;
}
@GetMapping("/ai/generate")
public Map<String, String> generate(
@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return Map.of("generation", this.chatModel.call(message));
}
@GetMapping("/ai/generateStream")
public Flux<ChatResponse> generateStream(
@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
Prompt prompt = new Prompt(new UserMessage(message));
return this.chatModel.stream(prompt);
}
}9. 受支持的模型
Perplexity 提供多种针对搜索增强对话优化的模型,常用:
| 模型 | 说明 |
|---|---|
llama-3.1-sonar-small-128k-online | 小型模型,128K 上下文,支持在线搜索 |
llama-3.1-sonar-large-128k-online | 大型模型,128K 上下文,支持在线搜索 |
llama-3.1-sonar-huge-128k-online | 超大型模型,128K 上下文,支持在线搜索 |
llama-3.1-8b-instruct | 离线(不联网)小型模型 |
llama-3.1-70b-instruct | 离线大型模型 |
完整列表请参考 https://docs.perplexity.ai/guides/model-cards。
10. 注意事项
注意
- Perplexity 不支持 tool calling、多模态、embedding,所以接入时要禁用对应的 auto-configuration。
- "Online" 系列模型会自动联网搜索,"instruct" 系列不会。
- 受速率限制影响,参考 https://docs.perplexity.ai/guides/rate-limits。
11. 小结
Perplexity 的最大卖点是自带联网搜索,回答问题时会附带最新的网络资料。如果你的应用是"问答 + 时效性"场景(新闻摘要、股票查询、最新技术问答),Perplexity 是个非常省心的方案——不用自己写搜索 + 总结的 pipeline。
接入方式跟其他 OpenAI 兼容厂商一样:换 base-url + 换 api-key + 选模型。
OCI Generative AI Chat
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/oci-genai-chat.html 📌 原文版本:Java AI 2.0.1
白话解读
这一页在 Java AI 2.0.1 中是个简短通知页,Oracle Cloud Infrastructure(OCI)Generative AI 集成已经从 Java AI 主仓库迁出,由社区维护。
1. 官方说明
原文翻译如下:
Oracle Cloud Infrastructure Generative AI 集成目前已由社区维护,请参阅相关文档了解详情。
英文原文:
The Oracle Cloud Infrastructure Generative AI integration is now maintained by the community, please see the related documentation for more details.
2. 含义解读
这则通知告诉我们:
- Java AI 主项目不再维护 OCI Generative AI 模块
- 完整文档、Maven 坐标、auto-configuration 类、配置属性等已迁移到社区仓库
- 2.0.1 版本的当前页面只保留了导航入口,没有具体技术内容
3. 替代方案
如果你需要在 Java AI 项目里接入 OCI Generative AI,可以从以下几个方向入手:
3.1 旧版文档
切换到 Java AI 1.0.9 或 1.1.8 版本(这些版本可能还保留完整文档):
https://docs.spring.io/spring-ai/reference/1.0.x/api/chat/oci-genai-chat.html
https://docs.spring.io/spring-ai/reference/1.1.x/api/chat/oci-genai-chat.html3.2 社区维护仓库
按照官方提示,去 Java AI 社区文档仓库查找 OCI GenAI 模块的新位置。
3.3 直接使用 OCI Java SDK
OCI 官方提供 Java SDK(oci-java-sdk),你可以:
- 在 Maven 中引入
com.oracle.oci.sdk:oci-java-sdk。 - 用
GenerativeAi客户端直接调用 OCI 上的 Cohere、Meta Llama 等模型。 - 把 OCI SDK 的返回结果适配到 Java AI 的
ChatResponse。
3.4 走 OpenAI 兼容协议
OCI Generative AI 部分模型支持 OpenAI 兼容端点,可以复用 Java AI 的 OpenAI 客户端:
spring:
ai:
openai:
base-url: https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/v1
api-key: ${OCI_CONFIG_PROFILE_TOKEN}
chat:
model: meta.llama-3.1-70b-instruct注意
OpenAI 兼容协议是 OCI 后来加的能力,不一定覆盖所有模型,请参考 OCI 官方文档确认。
4. OCI Generative AI 模型简介
为了便于上下文理解,这里列出 OCI 平台上常见的几类托管模型:
| 模型家族 | 说明 |
|---|---|
cohere.command-r-plus | Cohere Command R Plus,对话增强 |
cohere.command-r | Cohere Command R,性价比款 |
meta.llama-3.1-405b-instruct | Llama 3.1 405B 旗舰 |
meta.llama-3.1-70b-instruct | Llama 3.1 70B |
meta.llama-3.2-90b-vision-instruct | Llama 3.2 90B 多模态 |
具体可用模型请到 https://docs.oracle.com/en-us/iaas/Content/generative-ai/home.htm 查阅。
5. 历史背景
上下文
Java AI 1.x 时代提供过完整的 OCI Generative AI 集成 starter,支持 Chat、Embedding、Cohere 等多种模型。但随着 Java AI 架构调整(部分厂商模块迁移到官方 Java SDK 模式),OCI 模块被剥离到社区维护。这一变化与"Migrating the Anthropic Module to the Official Java SDK" 的迁移方向一致。
6. 小结
本页面在 Java AI 2.0.1 中没有实质技术内容。如果你需要使用 OCI Generative AI:
- 查阅 旧版文档(1.0.x / 1.1.x)
- 关注 社区仓库的新文档
- 或直接用 OCI Java SDK + 自定义适配
随着 Java AI 演进,OCI 模块可能会重新整合,但目前以社区文档为准。
OpenAI Chat(上篇:基础与高级能力)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/openai-chat.html 📌 原文版本:Java AI 2.0.1
白话解读
OpenAI 是 Java AI 的"标杆"——大量能力(结构化输出、多模态、推理模型、工具调用、流式、可观测)都是先在 OpenAI 客户端落地,再被其他厂商借鉴。这篇内容非常长,拆成上、下两篇来讲。
1. 简介
OpenAI 是 ChatGPT 背后的厂商,提供业界领先的 GPT 系列模型。Java AI 在 2.0.0-M5 起底层切到官方 openai-java SDK,对接对老用户是无缝的,没有破坏性变更。
支持的常用模型:
- gpt-5 / gpt-5-mini / gpt-5-nano / gpt-5-chat:最新 GPT-5 系列
- gpt-4o / gpt-4o-mini:经典多模态模型
- gpt-4-turbo / gpt-4:GPT-4 系列
- o1 / o3 / o4-mini:推理模型
- gpt-audio:音频多模态
2. 准备工作
2.1 创建 API Key
- 在 https://platform.openai.com 注册账号。
- 到 https://platform.openai.com/api-keys 生成 API Key。
- 把 Key 配置到
spring.ai.openai.api-key。
2.2 安全做法(环境变量)
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}export OPENAI_API_KEY=<your-openai-api-key>或代码里读取:
String apiKey = System.getenv("OPENAI_API_KEY");3. 自动配置
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>Gradle:
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-openai'
}4. 连接属性
| 属性 | 描述 | 默认值 |
|---|---|---|
spring.ai.openai.base-url | API 入口 | api.openai.com |
spring.ai.openai.api-key | API Key | - |
spring.ai.openai.organization-id | 组织 ID(多组织用户使用) | - |
spring.ai.openai.project-id | 项目 ID(多项目用户使用) | - |
spring.ai.openai.timeout | 请求超时 | 60 sec |
spring.ai.openai.max-retries | 客户端内置最大重试 | 3 |
spring.ai.openai.proxy | 代理设置 | - |
spring.ai.openai.custom-headers | 自定义 HTTP 头 | empty |
spring.ai.openai.connection-pool-metrics-enabled | 是否启用 OkHttp 连接池指标 | false |
小提示
Java AI 自动发送 User-Agent: java-ai 头,方便 OpenAI 识别来自 Java AI 的调用。
5. 聊天属性(Chat Options)
5.1 启用开关
spring:
ai:
model:
chat: openai # 默认启用 OpenAI
# chat: none # 禁用5.2 全量配置
| 属性 | 描述 | 默认值 |
|---|---|---|
spring.ai.openai.chat.model | 模型名 | gpt-5-mini |
spring.ai.openai.chat.temperature | 温度(采样随机性) | 0.8 |
spring.ai.openai.chat.frequency-penalty | 频率惩罚(-2~2) | 0.0f |
spring.ai.openai.chat.logit-bias | 调整指定 token 的可能性 | - |
spring.ai.openai.chat.max-tokens | 非推理模型最大生成 token 数 | - |
spring.ai.openai.chat.max-completion-tokens | 推理模型最大生成 token 数 | - |
spring.ai.openai.chat.n | 每个输入生成多少选择 | 1 |
spring.ai.openai.chat.store | 是否存储以供模型改进 | false |
spring.ai.openai.chat.metadata | 开发者标签用于过滤 | empty |
spring.ai.openai.chat.output-modalities | 输出类型(文本、音频) | - |
spring.ai.openai.chat.output-audio | 音频参数(voice + format) | - |
spring.ai.openai.chat.presence-penalty | 存在惩罚(-2~2) | - |
spring.ai.openai.chat.response-format.type | JSON_OBJECT / JSON_SCHEMA | - |
spring.ai.openai.chat.response-format.name | JSON Schema 名 | custom_schema |
spring.ai.openai.chat.response-format.schema | JSON Schema 内容 | - |
spring.ai.openai.chat.response-format.strict | 是否严格遵循 schema | - |
spring.ai.openai.chat.seed | 随机种子(确定性生成) | - |
spring.ai.openai.chat.stop | 停止序列(最多 4 个) | - |
spring.ai.openai.chat.top-p | 核采样阈值 | - |
spring.ai.openai.chat.tools | 工具列表 | - |
spring.ai.openai.chat.tool-choice | 工具选择策略 | - |
spring.ai.openai.chat.user | 最终用户唯一标识(滥用监控) | - |
spring.ai.openai.chat.stream-usage | 流式最后是否带 usage chunk | false |
spring.ai.openai.chat.parallel-tool-calls | 是否允许并行函数调用 | true |
spring.ai.openai.chat.prompt-cache-key | 缓存键(降低延迟/成本) | - |
spring.ai.openai.chat.safety-identifier | 安全标识(哈希值) | - |
spring.ai.openai.chat.http-headers | 自定义 HTTP 头 | - |
spring.ai.openai.chat.tool-callbacks | Tool Callbacks | - |
spring.ai.openai.chat.service-tier | 服务层级 | - |
spring.ai.openai.chat.extra-body | 额外参数(OpenAI 兼容服务器用) | - |
5.3 重要限制说明
注意
- GPT-5 系列不支持 temperature(gpt-5、gpt-5-mini、gpt-5-nano)。指定会报错。gpt-5-chat 支持。
- 本地 Docker Model Runner 需要
/v1:spring.ai.openai.chat.base-url=http://localhost:12434/engines/v1。 maxTokens与maxCompletionTokens互斥:同时设置会导致 API 报错。
5.4 覆盖通用属性
spring:
ai:
openai:
base-url: https://api.openai.com # 通用 base-url
chat:
base-url: https://chat.openai.com # 聊天专用,覆盖通用
api-key: sk-chat-key # 聊天专用 Key6. Token 限制参数
OpenAI 提供两个互斥参数来控制 token 上限:
| 参数 | 适用模型 | 互斥关系 |
|---|---|---|
maxTokens | 非推理模型(gpt-4o、gpt-3.5-turbo) | 与 maxCompletionTokens 互斥 |
maxCompletionTokens | 推理模型(o1、o3、o4-mini) | 与 maxTokens 互斥 |
示例:
// 非推理模型:用 maxTokens
ChatResponse response = chatModel.call(
new Prompt("用简单的话解释量子计算",
OpenAiChatOptions.builder()
.model("gpt-4o")
.maxTokens(150)
.build()));
// 推理模型:用 maxCompletionTokens
ChatResponse response = chatModel.call(
new Prompt("分步解这个复杂的数学题...",
OpenAiChatOptions.builder()
.model("o1-preview")
.maxCompletionTokens(1000)
.build()));构建器自动按"后设置者胜出"方式强制互斥:
OpenAiChatOptions options = OpenAiChatOptions.builder()
.maxTokens(100) // 先设置
.maxCompletionTokens(200) // 自动清空 maxTokens 并 warning
.build();
// 结果:maxTokens = null, maxCompletionTokens = 2007. 运行时选项
ChatResponse response = chatModel.call(
new Prompt("Generate the names of 5 famous pirates.",
OpenAiChatOptions.builder()
.model("gpt-4o")
.temperature(0.4)
.build()));也可以用 ChatOptions#builder() 创建可移植的 options 实例。
8. 工具调用
OpenAI 原生支持 function calling。Java AI 自动处理工具注册和执行:
@Bean
@Description("获取指定城市的天气")
FunctionToolCallback getWeatherTool() {
return FunctionToolCallback.builder("get_weather", new WeatherService())
.description("查询天气")
.build();
}ChatClient + ToolCallingAdvisor 会自动协调调用。详见「ChatModel Tool Calling」。
9. 多模态
9.1 视觉(Vision)
支持的模型:gpt-4、gpt-4o、gpt-4o-mini。
// 本地资源
var imageResource = new ClassPathResource("/multimodal.test.png");
var userMessage = new UserMessage("描述这张图片",
new Media(MimeTypeUtils.IMAGE_PNG, imageResource));
ChatResponse response = chatModel.call(new Prompt(userMessage,
OpenAiChatOptions.builder().model("gpt-4o").build()));
// 或者用 URL
var userMessage = new UserMessage("描述这张图片",
new Media(MimeTypeUtils.IMAGE_PNG,
URI.create("https://docs.spring.io/spring-ai/reference/_images/multimodal.test.png")));支持多张图片。
9.2 输入音频(Audio In)
支持的模型:gpt-audio。支持格式:audio/mp3、audio/wav。
var audioResource = new ClassPathResource("speech1.mp3");
var userMessage = new UserMessage("这段录音讲了什么?",
List.of(new Media(MimeTypeUtils.parseMimeType("audio/mp3"), audioResource)));
ChatResponse response = chatModel.call(new Prompt(List.of(userMessage),
OpenAiChatOptions.builder().model("gpt-audio").build()));9.3 输出音频(Audio Out)
var userMessage = new UserMessage("讲一个关于 Spring Framework 的笑话");
ChatResponse response = chatModel.call(new Prompt(List.of(userMessage),
OpenAiChatOptions.builder()
.model("gpt-audio")
.outputModalities(List.of("text", "audio")) // 同时输出文本+音频
.outputAudio(new AudioParameters(Voice.ALLOY, AudioResponseFormat.WAV))
.build()));
String text = response.getResult().getOutput().getText(); // 文本转写
byte[] waveAudio = response.getResult().getOutput().getMedia().get(0) // 音频字节
.getDataAsByteArray();10. 结构化输出
OpenAI 提供官方的"Structured Outputs" API,保证模型输出严格符合你提供的 JSON Schema。Java AI 用 ResponseFormat 包装它。
10.1 编程式配置
String jsonSchema = """
{
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": { "type": "string" },
"output": { "type": "string" }
},
"required": ["explanation", "output"],
"additionalProperties": false
}
},
"final_answer": { "type": "string" }
},
"required": ["steps", "final_answer"],
"additionalProperties": false
}
""";
Prompt prompt = new Prompt("解方程 8x + 7 = -23",
OpenAiChatOptions.builder()
.model(ChatModel.GPT_4_O_MINI)
.responseFormat(new ResponseFormat(ResponseFormat.Type.JSON_SCHEMA, jsonSchema))
.build());
ChatResponse response = openAiChatModel.call(prompt);10.2 与 BeanOutputConverter 集成
record MathReasoning(
@JsonProperty(required = true, value = "steps") Steps steps,
@JsonProperty(required = true, value = "final_answer") String finalAnswer) {
record Steps(
@JsonProperty(required = true, value = "items") Items[] items) {
record Items(
@JsonProperty(required = true, value = "explanation") String explanation,
@JsonProperty(required = true, value = "output") String output) {}
}
}
var converter = new BeanOutputConverter<>(MathReasoning.class);
String jsonSchema = converter.getJsonSchema();
Prompt prompt = new Prompt("解方程 8x + 7 = -23",
OpenAiChatOptions.builder()
.model(ChatModel.GPT_4_O_MINI)
.responseFormat(new ResponseFormat(ResponseFormat.Type.JSON_SCHEMA, jsonSchema))
.build());
ChatResponse response = openAiChatModel.call(prompt);
MathReasoning result = converter.convert(response.getResult().getOutput().getText());注意
OpenAI 强制要求 schema 里标记 required 字段,否则结构化输出可能异常工作。
10.3 配置文件方式
spring.ai.openai.api-key=YOUR_API_KEY
spring.ai.openai.chat.model=gpt-4o-mini
spring.ai.openai.chat.response-format.type=JSON_SCHEMA
spring.ai.openai.chat.response-format.name=MySchemaName
spring.ai.openai.chat.response-format.schema={"type":"object","properties":{"steps":{"type":"array","items":{"type":"object","properties":{"explanation":{"type":"string"},"output":{"type":"string"}},"required":["explanation","output"],"additionalProperties":false}},"final_answer":{"type":"string"}},"required":["steps","final_answer"],"additionalProperties":false}
spring.ai.openai.chat.response-format.strict=true11. 小结
上篇覆盖了 OpenAI Chat 的基础配置、属性、token 限制、运行时选项、工具调用、多模态、结构化输出。下篇继续讲示例控制器、手动配置、API Key 管理、可观测性、HTTP 客户端自定义、推理内容、OpenAI 兼容服务器额外参数等进阶主题。
OpenAI Chat(下篇:高级特性)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/chat/openai-chat.html 📌 原文版本:Java AI 2.0.1
白话解读
本篇是 OpenAI Chat 的"下篇",聚焦在 HTTP 客户端定制、可观测性、推理内容、OpenAI 兼容服务器的额外参数等进阶话题。读完能让你把 OpenAI 客户端用到生产级水平。
1. 示例控制器
spring.ai.openai.api-key=YOUR_API_KEY
spring.ai.openai.chat.model=gpt-4o
spring.ai.openai.chat.temperature=0.7@RestController
public class ChatController {
private final OpenAiChatModel chatModel;
@Autowired
public ChatController(OpenAiChatModel chatModel) {
this.chatModel = chatModel;
}
@GetMapping("/ai/generate")
public Map<String, String> generate(
@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return Map.of("generation", this.chatModel.call(message));
}
@GetMapping("/ai/generateStream")
public Flux<ChatResponse> generateStream(
@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
Prompt prompt = new Prompt(new UserMessage(message));
return this.chatModel.stream(prompt);
}
}2. 手动配置(不用 Starter)
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai</artifactId>
</dependency>var chatModel = OpenAiChatModel.builder()
.options(OpenAiChatOptions.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.model("gpt-3.5-turbo")
.temperature(0.4)
.maxTokens(200)
.build())
.build();
ChatResponse response = chatModel.call(new Prompt("Generate the names of 5 famous pirates."));
// 或流式
Flux<ChatResponse> stream = chatModel.stream(new Prompt("Generate the names of 5 famous pirates."));3. API Key 管理
Java AI 通过 ApiKey 接口管理密钥,默认实现 SimpleApiKey 适用大多数场景。
3.1 默认配置
spring.ai.openai.api-key=your-api-key-here3.2 自定义 API Key 逻辑
如果需要从密钥库动态取 Key、轮换 Key,可以实现 ApiKey 接口:
ApiKey customApiKey = new ApiKey() {
@Override
public String getValue() {
// 自定义逻辑:从 Vault、KMS、数据库取 Key
return "your-api-key-here";
}
};
OpenAiChatModel chatModel = OpenAiChatModel.builder()
.options(OpenAiChatOptions.builder()
.apiKey(customApiKey.getValue())
.build())
.build();
ChatClient openAiChatClient = ChatClient.builder(chatModel).build();适用场景:
- 从密钥库检索 API Key(Vault / AWS KMS)
- 动态轮换 Key
- 实现自定义选择逻辑(多 Key 池、A/B 路由)
4. 可观测性(Observability)
Java AI 通过 Micrometer 在两个层级发出 observation:
4.1 Chat Model 层
每次 OpenAiChatModel.call(...) 或 .stream(...) 调用都会触发:
- observation 名:
gen_ai.client.operation - 携带:请求参数、响应元数据、token 使用情况
4.2 HTTP 层
每次 HTTP 请求都会触发:
- observation 名:
okhttp.requests - 携带:HTTP 方法、URI、状态码、异常标签
- 通过
traceparent把 trace 上下文传播到下游服务
4.3 自动连接
在 Spring Boot 项目里,只要引入:
spring-boot-starter-actuatormicrometer-tracing-bridge-otel或micrometer-tracing-bridge-brave
两个层级就自动连接,无需 opt-in。
4.4 非 Boot 项目手动连接
OpenAiChatModel chatModel = OpenAiChatModel.builder()
.options(...)
.observationRegistry(observationRegistry) // 注入 ObservationRegistry
.build();5. 连接池指标(OPT-IN)
Java AI 默认不开启 OkHttp 连接池 gauges,需要 opt-in:
spring.ai.openai.chat.connection-pool-metrics-enabled=true非 Boot 项目:
OpenAiChatModel chatModel = OpenAiChatModel.builder()
.options(...)
.observationRegistry(observationRegistry)
.meterRegistry(meterRegistry) // 注入 MeterRegistry
.build();指标名:okhttp.pool.connection.count,标签:state=active|idle、client.kind=sync|async。
6. HTTP 调度器执行器
默认 Java AI 用一个无界平台线程池作为 OkHttp 调度器(复现 SDK 原行为)。高并发或想用 Java 21+ 虚拟线程的话,可以注入自己的 ExecutorService:
OpenAiChatModel chatModel = OpenAiChatModel.builder()
.options(...)
.dispatcherExecutor(Executors.newVirtualThreadPerTaskExecutor()) // 虚拟线程
.build();注意
当你提供自己的 ExecutorService 时,生命周期由你管理,Java AI 不会调用 shutdown()。
7. 流式 HTTP observations 的特殊性
架构说明
对于同步调用,okhttp.requests span 正确嵌套在 gen_ai.client.operation span 下。
对于流式调用,okhttp.requests span 触发并记录在 registry 中,traceparent 仍在出站请求上传播——但 span 不嵌套在 chat-model span 下。原因是 OpenAI SDK 的异步流式实现在调用 Java AI HTTP 客户端之前会跳转到 ForkJoinPool.commonPool(),在那个边界丢弃了调用线程的 observation 上下文。
如果需要在追踪 UI 中手动连父子 span,可以按 span 名 okhttp.requests、主机 api.openai.com、trace ID 或时间戳范围过滤。
8. 自定义 HTTP 客户端
Java AI 底层用官方 openai-java SDK + 自定义 OkHttp 客户端(SpringAiOpenAiHttpClient.Builder)。你可以通过暴露 OpenAiHttpClientBuilderCustomizer bean 拦截底层 OkHttp 客户端的构建:
@FunctionalInterface
public interface OpenAiHttpClientBuilderCustomizer {
void customize(SpringAiOpenAiHttpClient.Builder builder);
}典型用例:
- 注册 OkHttp Interceptor(鉴权、传播头、自定义日志)
- 替换调度器 ExecutorService(路由到虚拟线程)
- 配置代理、SSL、主机名验证、连接池大小
多个 customizer 按 @Order / Ordered 顺序应用,在 Java AI 默认值之后,所以用户代码获胜。
手动连接时同样可用:
var chatModel = OpenAiChatModel.builder()
.options(OpenAiChatOptions.builder().model("gpt-4o").build())
.httpClientBuilderCustomizer(myCustomizer)
.build();9. OpenAI 兼容服务器的额外参数
vLLM、Ollama 等兼容 OpenAI 的推理服务器通常支持超出 OpenAI 标准 API 的额外参数(如 top_k、repetition_penalty)。extraBody 选项让你把这些参数传给服务器。
注意
extraBody 只用于 OpenAI 兼容服务器,官方 OpenAI API 会因无法识别字段返回 HTTP 400。
extraBody 会被扁平化到 JSON 请求顶层:
// 设置 extraBody
.extraBody(Map.of("custom_flag", true))
// 产生的请求体根处会有 custom_flag
{"custom_flag": true, ...}9.1 通过属性配置
spring.ai.openai.base-url=http://localhost:8000
spring.ai.openai.chat.model=meta-llama/Llama-3-8B-Instruct
spring.ai.openai.chat.temperature=0.7
spring.ai.openai.chat.extra-body.top_k=50
spring.ai.openai.chat.extra-body.repetition_penalty=1.19.2 通过构建器运行时配置
ChatResponse response = chatModel.call(
new Prompt("讲个有创意的故事",
OpenAiChatOptions.builder()
.model("meta-llama/Llama-3-8B-Instruct")
.temperature(0.7)
.extraBody(Map.of(
"top_k", 50,
"repetition_penalty", 1.1,
"frequency_penalty", 0.5))
.build()));9.3 vLLM 示例
spring.ai.openai.base-url=http://localhost:8000
spring.ai.openai.chat.model=meta-llama/Llama-3-70B-Instruct
spring.ai.openai.chat.extra-body.top_k=40
spring.ai.openai.chat.extra-body.top_p=0.95
spring.ai.openai.chat.extra-body.repetition_penalty=1.05
spring.ai.openai.chat.extra-body.min_p=0.059.4 Ollama 示例
OpenAiChatOptions options = OpenAiChatOptions.builder()
.model("llama3.2")
.extraBody(Map.of(
"num_predict", 100,
"top_k", 40,
"repeat_penalty", 1.1))
.build();extraBody 接受任意 Map<String, Object>,Java AI 不验证参数——直接传递给服务器。
10. 推理模型的推理内容(Reasoning Content)
部分 OpenAI 兼容服务器(DeepSeek R1、vLLM 推理解析器)在响应里提供 reasoning_content 字段,把模型的内部思维链暴露出来。
Java AI 把这个字段映射到 AssistantMessage 元数据的 reasoningContent 键。
10.1 重要区别
| 场景 | 是否暴露推理内容 |
|---|---|
| OpenAI 兼容服务器(DeepSeek、vLLM) | ✅ 暴露 reasoning_content |
| 官方 OpenAI 模型(GPT-5、o1、o3) | ❌ 只暴露 reasoning_tokens 计数 |
上下文
官方 OpenAI 推理模型使用 Chat Completions API 时隐藏思维链。要访问实际推理文本,必须用 OpenAI Responses API(Java AI 暂不支持)。
回退行为:服务器未提供 reasoning_content 时,元数据字段为空字符串。
10.2 访问推理内容
ChatResponse response = chatModel.call(
new Prompt("9.11 和 9.9 哪个更大?"));
AssistantMessage message = response.getResult().getOutput();
String reasoning = message.getMetadata().get("reasoningContent");
String answer = message.getContent();ChatClient 写法:
String result = chatClient.prompt()
.user("9.11 和 9.9 哪个更大?")
.call()
.chatResponse()
.getResult()
.getOutput()
.getContent();
ChatResponse response = chatClient.prompt()
.user("9.11 和 9.9 哪个更大?")
.call()
.chatResponse();
AssistantMessage message = response.getResult().getOutput();
String reasoning = message.getMetadata().get("reasoningContent");10.3 流式推理内容
Flux<ChatResponse> flux = chatModel.stream(new Prompt("解这个逻辑谜题..."));
StringBuilder reasoning = new StringBuilder();
StringBuilder answer = new StringBuilder();
flux.subscribe(chunk -> {
AssistantMessage message = chunk.getResult().getOutput();
String reasoningChunk = message.getMetadata().get("reasoningContent");
if (reasoningChunk != null) {
reasoning.append(reasoningChunk); // 累积推理
}
if (message.getContent() != null) {
answer.append(message.getContent()); // 累积最终答案
}
});10.4 DeepSeek R1 示例
spring.ai.openai.api-key=${DEEPSEEK_API_KEY}
spring.ai.openai.base-url=https://api.deepseek.com
spring.ai.openai.chat.model=deepseek-reasoner响应同时包含 reasoning_content 和最终答案。
10.5 vLLM 推理解析器示例
vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B \
--enable-reasoning \
--reasoning-parser deepseek_r1spring.ai.openai.base-url=http://localhost:8000
spring.ai.openai.chat.model=deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B11. 工具调用的额外属性(Google Gemini 兼容)
部分 OpenAI 兼容厂商会在 tool-call 对象里附加额外字段。典型例子是 Google Gemini 的 OpenAI 兼容端点:
{
"tool_calls": [{
"id": "call_1",
"type": "function",
"function": { "name": "get_weather", "arguments": "{\"location\":\"Seoul\"}" },
"extra_content": { "google": { "thought_signature": "..." } }
}]
}如果后续请求中缺这些字段,某些模型会拒绝工具调用历史。
Java AI 自动捕获 tool-call 对象上的额外字段,并在 assistant 消息被包含进后续请求时逐字重放它们,无需配置——对阻塞和流式都透明。
限制
只保留 tool-call 对象本身的额外字段,嵌套 function 对象内的额外字段不会被保留。
12. 小结
下篇把 OpenAI 客户端讲深了一层,覆盖:
- 可观测性:Micrometer 双层 observation、连接池指标
- HTTP 自定义:dispatcher executor、OkHttp client 拦截
- extraBody:用 OpenAI 客户端访问 vLLM、Ollama 等扩展参数
- reasoningContent:从 OpenAI 兼容服务器读推理过程
- 工具调用额外字段:跨厂商兼容(Gemini thought_signature)
这些能力让 OpenAI 客户端不仅是 OpenAI 的客户端,也是所有 OpenAI 兼容生态的统一入口。
OpenAI Chat 的内容到此结束。下一页开始处理 Embedding Models 章节。