Ollama 聊天
使用 Ollama,您可以在本地运行各种大型语言模型(LLM)并从中生成文本。Spring AI 通过 OllamaChatModel API 支持 Ollama 的聊天补全功能。
前置条件
首先,您需要访问一个 Ollama 实例。有几种方式可供选择,包括:
- 在本地计算机上 下载并安装 Ollama。
- 通过 Testcontainers 配置并 运行 Ollama。
- 通过 Kubernetes 服务 绑定连接到 Ollama 实例。
您可以从 Ollama 模型库 中拉取应用中需要使用的模型:
ollama pull <model-name>
您也可以拉取成千上万免费的 GGUF Hugging Face 模型:
ollama pull hf.co/<username>/<model-repository>
另外,您还可以启用 自动拉取模型 选项,以自动下载所需的模型。
自动配置
Spring AI 的自动配置以及 starter 模块的制品(artifact)名称发生了较大的变更。更多信息请参阅 升级说明。
Spring AI 为 Ollama 聊天集成提供了 Spring Boot 自动配置。要启用该功能,请在项目的 Maven pom.xml 或 Gradle build.gradle 文件中添加如下依赖:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
</dependency>
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-ollama'
}
基础属性
spring.ai.ollama 是用于配置 Ollama 连接的属性前缀。
| 属性 | 说明 | 默认值 |
|---|---|---|
spring.ai.ollama.base-url | Ollama API 服务运行的基础 URL | http://localhost:11434 |
下面是用于初始化 Ollama 集成以及 自动拉取模型 的相关属性。
| 属性 | 说明 | 默认值 |
|---|---|---|
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 | 除默认属性中配置的模型外,额外需要初始化的模型列表 | [] |
聊天属性
spring.ai.model.chat 来进行配置。- 启用:
spring.ai.model.chat=ollama(默认已启用) - 禁用:
spring.ai.model.chat=none(或任何不匹配ollama的值)
spring.ai.ollama.chat.options 是用于配置 Ollama 聊天模型的属性前缀。它包含 Ollama 请求的高级参数(如 model、keep-alive、format 等)以及 Ollama 模型本身的选项。
Ollama Chat 模型高级请求参数:
| 属性 | 说明 | 默认值 |
|---|---|---|
spring.ai.ollama.chat.enabled(已移除,不再有效) | 启用 Ollama 聊天模型 | true |
spring.ai.model.chat | 启用 Ollama 聊天模型 | ollama |
spring.ai.ollama.chat.options.model | 使用的受支持模型名称 | mistral |
spring.ai.ollama.chat.options.format | 返回结果的格式,目前仅支持 json | - |
spring.ai.ollama.chat.options.keep_alive | 请求完成后模型在内存中保持加载的时间 | 5m |
其余的选项属性基于 Ollama 的有效参数与取值 以及 Ollama Types 定义;其默认值则来源于 Ollama Types 的默认配置。
| 属性 | 说明 | 默认值 |
|---|---|---|
spring.ai.ollama.chat.options.numa | 是否使用 NUMA | false |
spring.ai.ollama.chat.options.num-ctx | 用于生成下一个 token 的上下文窗口大小 | 2048 |
spring.ai.ollama.chat.options.num-batch | 提示词处理的最大批处理大小 | 512 |
spring.ai.ollama.chat.options.num-gpu | 发送到 GPU 的层数(macOS 默认 1 启用 Metal,0 表示禁用;1 表示动态设置) | -1 |
spring.ai.ollama.chat.options.main-gpu | 多 GPU 场景下用于小张量计算的 GPU 索引 | 0 |
spring.ai.ollama.chat.options.low-vram | 低显存模式 | false |
spring.ai.ollama.chat.options.f16-kv | 使用 FP16 的 KV 缓存 | true |
spring.ai.ollama.chat.options.logits-all | 返回所有 token 的 logits(启用 logprobs 需要为 true) | - |
spring.ai.ollama.chat.options.vocab-only | 仅加载词表,不加载权重 | - |
spring.ai.ollama.chat.options.use-mmap | 是否使用内存映射加载模型 | null |
spring.ai.ollama.chat.options.use-mlock | 将模型锁定在内存中,防止被交换 | false |
spring.ai.ollama.chat.options.num-thread | 计算时使用的线程数(0 表示运行时自动决定) | 0 |
spring.ai.ollama.chat.options.num-keep | - | 4 |
spring.ai.ollama.chat.options.seed | 随机数种子(固定后可复现输出) | -1 |
spring.ai.ollama.chat.options.num-predict | 最大生成 token 数(-1 无限,-2 填满上下文) | -1 |
spring.ai.ollama.chat.options.top-k | 限制候选 token 数,降低无意义输出 | 40 |
spring.ai.ollama.chat.options.top-p | 核采样概率阈值,控制多样性 | 0.9 |
spring.ai.ollama.chat.options.min-p | 最小概率过滤参数,用于平衡质量与多样性 | 0.0 |
spring.ai.ollama.chat.options.tfs-z | Tail-free sampling 参数(1.0 表示禁用) | 1.0 |
spring.ai.ollama.chat.options.typical-p | - | 1.0 |
spring.ai.ollama.chat.options.repeat-last-n | 防止重复时回溯的 token 数 | 64 |
spring.ai.ollama.chat.options.temperature | 温度参数,越高越有创造性 | 0.8 |
spring.ai.ollama.chat.options.repeat-penalty | 重复惩罚强度 | 1.1 |
spring.ai.ollama.chat.options.presence-penalty | - | 0.0 |
spring.ai.ollama.chat.options.frequency-penalty | - | 0.0 |
spring.ai.ollama.chat.options.mirostat | 启用 Mirostat 采样(0=禁用,1=Mirostat,2=Mirostat 2.0) | 0 |
spring.ai.ollama.chat.options.mirostat-tau | 控制一致性与多样性的平衡 | 5.0 |
spring.ai.ollama.chat.options.mirostat-eta | 学习率,控制算法响应速度 | 0.1 |
spring.ai.ollama.chat.options.penalize-newline | 是否惩罚换行 | true |
spring.ai.ollama.chat.options.stop | 停止生成的序列列表 | - |
spring.ai.ollama.chat.options.tool-names | 启用函数调用的工具名称列表 | - |
spring.ai.ollama.chat.options.tool-callbacks | 注册到 ChatModel 的工具回调 | - |
spring.ai.ollama.chat.options.internal-tool-execution-enabled | 是否由 Spring AI 内部处理工具调用 | true |
运行时选项
OllamaChatOptions.java 类用于提供模型相关的配置选项,例如要使用的模型、温度(temperature)、思考模式(thinking mode)等。
OllamaOptions 类已被弃用。对于聊天模型,请改用 OllamaChatOptions;对于向量嵌入模型,请使用 OllamaEmbeddingOptions。这些新的类提供了类型安全、模型专用的配置方式。在应用启动时,可以通过 OllamaChatModel(api, options) 构造函数,或使用 spring.ai.ollama.chat.options.* 配置属性来设置默认选项。
在运行时,你可以在 Prompt 调用中添加请求级别的新选项,以覆盖默认配置。例如,下面的示例展示了如何为某一次请求覆盖默认的模型和 temperature:
ChatResponse response = chatModel.call(
new Prompt(
"Generate the names of 5 famous pirates.",
OllamaChatOptions.builder()
.model(OllamaModel.LLAMA3_1)
.temperature(0.4)
.build()
));
自动拉取模型
Spring AI Ollama 支持在本地 Ollama 实例中 尚未存在模型时自动拉取模型。这一特性在 开发与测试阶段 以及 将应用部署到新环境 时尤为有用。
目前支持三种模型拉取策略:
- always(
PullModelStrategy.ALWAYS): 无论模型是否已存在,都会始终拉取。适合用于确保使用的是模型的最新版本。 - when_missing(
PullModelStrategy.WHEN_MISSING): 仅在模型尚不存在时才拉取。这种方式可能会使用到较旧版本的模型。 - never(
PullModelStrategy.NEVER): 从不自动拉取模型。
启动时自动拉取模型
所有通过配置属性或默认选项定义的模型,都可以在应用启动时自动拉取。你可以通过以下配置来控制拉取策略、超时时间和最大重试次数:
spring:
ai:
ollama:
init:
pull-model-strategy: always
timeout: 60s
max-retries: 1
你还可以在启动时初始化 额外的模型,这在运行时需要动态使用不同模型的场景下非常有用:
spring:
ai:
ollama:
init:
pull-model-strategy: always
chat:
additional-models:
- llama3.2
- qwen2.5
如果你只希望对特定类型的模型应用拉取策略,可以将聊天模型从初始化任务中排除:
spring:
ai:
ollama:
init:
pull-model-strategy: always
chat:
include: false
上述配置表示:对除聊天模型以外的所有模型应用自动拉取策略。
函数调用
你可以将 自定义的 Java 函数 注册到 OllamaChatModel 中,让 Ollama 模型 智能地选择并输出一个包含参数的 JSON 对象,以调用一个或多个已注册的函数。这是一种将 LLM 的能力与外部工具和 API 进行连接的强大技术。更多信息请参阅 Tool Calling 相关文档。
思维模式(推理)
Ollama 为具备推理能力的模型提供了 思考模式(Thinking Mode),这些模型可以在给出最终答案之前输出其 内部推理过程。该功能适用于 Qwen3、DeepSeek-v3.1、DeepSeek R1 以及 GPT-OSS 等模型。
- 支持思考的模型(例如
qwen3:*-thinking、deepseek-r1、deepseek-v3.1)在未显式设置think选项时,会默认启用思考模式。 - 普通模型(例如
qwen2.5:*、llama3.2)则默认不启用思考模式。
.enableThinking() 或 .disableThinking()。启用思维模式
大多数模型(如 Qwen3、DeepSeek-v3.1、DeepSeek R1)都支持通过简单的布尔开关来 启用或禁用思考模式:
ChatResponse response = chatModel.call(
new Prompt(
"单词 'strawberry' 中有多少个字母 'r'?",
OllamaChatOptions.builder()
.model("qwen3")
.enableThinking()
.build()
));
// 访问思考过程
String thinking = response.getResult().getMetadata().get("thinking");
String answer = response.getResult().getOutput().getContent();
你也可以显式 禁用思考模式:
ChatResponse response = chatModel.call(
new Prompt(
"2 + 2 等于多少?",
OllamaChatOptions.builder()
.model("deepseek-r1")
.disableThinking()
.build()
));
思维等级(仅 GPT-OSS)
GPT-OSS 模型 需要显式指定 思考级别,而不是使用简单的布尔值开关:
// 低思考级别
ChatResponse response = chatModel.call(
new Prompt(
"生成一个简短的标题",
OllamaChatOptions.builder()
.model("gpt-oss")
.thinkLow()
.build()
));
// 中等思考级别
ChatResponse response = chatModel.call(
new Prompt(
"分析这个数据集",
OllamaChatOptions.builder()
.model("gpt-oss")
.thinkMedium()
.build()
));
// 高思考级别
ChatResponse response = chatModel.call(
new Prompt(
"解决这个复杂问题",
OllamaChatOptions.builder()
.model("gpt-oss")
.thinkHigh()
.build()
));
访问思维内容
思考内容(thinking content)可以在响应的元数据中获取:
ChatResponse response = chatModel.call(
new Prompt(
"计算 17 × 23",
OllamaChatOptions.builder()
.model("deepseek-r1")
.enableThinking()
.build()
));
// 获取推理过程
String thinking = response.getResult().getMetadata().get("thinking");
System.out.println("推理过程: " + thinking);
// 输出示例: "17 × 20 = 340, 17 × 3 = 51, 340 + 51 = 391"
// 获取最终答案
String answer = response.getResult().getOutput().getContent();
System.out.println("答案: " + answer);
// 输出示例: "答案是 391"
思维模式下的流式输出
思考模式同样适用于流式响应(streaming responses):
Flux<ChatResponse> stream = chatModel.stream(
new Prompt(
"解释量子纠缠",
OllamaChatOptions.builder()
.model("qwen3")
.enableThinking()
.build()
));
stream.subscribe(response -> {
String thinking = response.getResult().getMetadata().get("thinking");
String content = response.getResult().getOutput().getContent();
if (thinking != null && !thinking.isEmpty()) {
System.out.println("[思考] " + thinking);
}
if (content != null && !content.isEmpty()) {
System.out.println("[响应] " + content);
}
});
thinking 元数据字段将为 null 或为空。多模态
多模态(Multimodality)指模型能够同时理解和处理来自不同来源的信息,包括文本、图像、音频以及其他数据格式。
Ollama 中部分支持多模态的模型包括 LLaVA 和 BakLLaVA(完整列表 请参考官方文档)。更多详情可参考 LLaVA: Large Language and Vision Assistant。
Ollama 的 Message API 提供了一个 images 参数,用于在消息中附加一组 Base64 编码的图片。
Spring AI 的 Message 接口通过引入 Media 类型来支持多模态 AI 模型。该类型包含消息中媒体附件的数据和详细信息,使用 Spring 的 org.springframework.util.MimeType 以及 org.springframework.core.io.Resource 来表示原始媒体数据。
下面是一个来自 OllamaChatModelMultimodalIT.java 的简单代码示例,展示了用户文本与图片的结合使用:
var imageResource = new ClassPathResource("/multimodal.test.png");
var userMessage = new UserMessage(
"解释你在这张图片中看到了什么?",
new Media(MimeTypeUtils.IMAGE_PNG, this.imageResource)
);
ChatResponse response = chatModel.call(
new Prompt(this.userMessage,
OllamaChatOptions.builder().model(OllamaModel.LLAVA).build())
);
示例中,模型接收 multimodal.test.png 图片和文本消息 "解释你在这张图片中看到了什么?" 作为输入,并生成类似如下的响应:

The image shows a small metal basket filled with ripe bananas and red apples. The basket is placed on a surface,
which appears to be a table or countertop, as there's a hint of what seems like a kitchen cabinet or drawer in
the background. There's also a gold-colored ring visible behind the basket, which could indicate that this
photo was taken in an area with metallic decorations or fixtures. The overall setting suggests a home environment
where fruits are being displayed, possibly for convenience or aesthetic purposes.
结构化输出
Ollama 提供了自定义的结构化输出(Structured Outputs)API,可确保模型生成的响应严格符合你提供的 JSON Schema。除了现有的 Spring AI 通用模型结构化输出转换器(Structured Output Converter)之外,这些 API 提供了更高的控制力和精确度。
配置
Spring AI 允许你通过 OllamaChatOptions 构建器以编程方式配置响应格式。
使用 Chat Options Builder
你可以通过 OllamaChatOptions 构建器以编程方式设置响应格式,如下所示:
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("how can I solve 8x + 7 = -23",
OllamaChatOptions.builder()
.model(OllamaModel.LLAMA3_2.getName())
.format(new ObjectMapper().readValue(jsonSchema, Map.class))
.build());
ChatResponse response = this.ollamaChatModel.call(this.prompt);
与 BeanOutputConverter 工具集成
你可以利用现有的 BeanOutputConverter 工具自动从领域对象生成 JSON Schema,并将结构化响应转换为特定领域实例:
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 outputConverter = new BeanOutputConverter<>(MathReasoning.class);
Prompt prompt = new Prompt("how can I solve 8x + 7 = -23",
OllamaChatOptions.builder()
.model(OllamaModel.LLAMA3_2.getName())
.format(outputConverter.getJsonSchemaMap())
.build());
ChatResponse response = this.ollamaChatModel.call(this.prompt);
String content = this.response.getResult().getOutput().getText();
MathReasoning mathReasoning = this.outputConverter.convert(this.content);
@JsonProperty(required = true, …) 注解。虽然在 JSON Schema 中该注解是可选的,但为了结构化响应能正确工作,建议加上。OpenAI API 兼容性
Ollama 兼容 OpenAI API,你可以使用 Spring AI 的 OpenAI 客户端与 Ollama 进行交互并使用工具。为此,你需要将 OpenAI 的基础 URL 配置为 Ollama 实例:
spring.ai.openai.chat.base-url=http://localhost:11434
并选择 Ollama 提供的模型之一:
spring.ai.openai.chat.options.model=mistral
extraBody选项 传递 Ollama 特有的参数(例如 top_k、repeat_penalty、num_predict),从而在使用 OpenAI 客户端的同时充分利用 Ollama 的全部功能。
通过 OpenAI 兼容性获取推理内容
Ollama 的 OpenAI 兼容端点支持针对具有思维能力的模型(例如 qwen3:*-thinking、deepseek-r1、deepseek-v3.1)的 reasoning_content 字段。当使用 Spring AI 的 OpenAI 客户端访问 Ollama 时,模型的推理过程会被自动捕获,并通过响应的 metadata 提供。
reasoning_content 字段名称而非 thinking。以下示例展示了如何通过 OpenAI 客户端访问 Ollama 的推理内容:
// 配置 Spring AI OpenAI 客户端指向 Ollama
@Configuration
class OllamaConfig {
@Bean
OpenAiChatModel ollamaChatModel() {
var openAiApi = new OpenAiApi("http://localhost:11434", "ollama");
return new OpenAiChatModel(openAiApi,
OpenAiChatOptions.builder()
.model("deepseek-r1") // 或 qwen3、deepseek-v3.1 等
.build());
}
}
// 使用思维能力模型
ChatResponse response = chatModel.call(
new Prompt("How many letter 'r' are in the word 'strawberry'?"));
// 从 metadata 中获取推理过程
String reasoning = response.getResult().getMetadata().get("reasoningContent");
if (reasoning != null && !reasoning.isEmpty()) {
System.out.println("模型的推理过程:");
System.out.println(reasoning);
}
// 获取最终答案
String answer = response.getResult().getOutput().getContent();
System.out.println("答案: " + answer);
可以参考 OllamaWithOpenAiChatModelIT.java 测试了解通过 Spring AI OpenAI 使用 Ollama 的示例。
HuggingFace 模型
Ollama 可以开箱即用地访问所有 GGUF Hugging Face 聊天模型。你可以通过名称拉取任意模型,例如:
ollama pull hf.co/<username>/<model-repository>
或者配置自动拉取策略(Auto-pulling Models):
spring.ai.ollama.chat.options.model=hf.co/bartowski/gemma-2-2b-it-GGUF
spring.ai.ollama.init.pull-model-strategy=always
spring.ai.ollama.chat.options.model:指定要使用的 Hugging Face GGUF 模型。spring.ai.ollama.init.pull-model-strategy=always(可选):在应用启动时自动拉取模型。对于生产环境,建议预先下载模型以避免延迟,例如:ollama pull hf.co/bartowski/gemma-2-2b-it-GGUF
示例控制器
创建 一个新的 Spring Boot 项目,并将 spring-ai-starter-model-ollama 添加到你的 pom.xml(或 gradle)依赖中。
在 src/main/resources 目录下添加一个 application.yaml 文件,以启用并配置 Ollama 聊天模型:
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
options:
model: mistral
temperature: 0.7
base-url 替换为你的 Ollama 服务器地址。这将创建一个 OllamaChatModel 实现,你可以将其注入到你的类中。以下是一个使用聊天模型生成文本的简单 @RestController 示例:
@RestController
public class ChatController {
private final OllamaChatModel chatModel;
@Autowired
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);
}
}
这个控制器提供了两个接口:
/ai/generate:同步生成文本响应。/ai/generateStream:以流式方式返回聊天响应。
手动配置
如果你不想使用 Spring Boot 自动配置,也可以在应用中手动配置 OllamaChatModel。OllamaChatModel 实现了 ChatModel 和 StreamingChatModel,并使用 低级别的 OllamaApi 客户端 连接 Ollama 服务。
首先,将 spring-ai-ollama 依赖添加到项目的 Maven pom.xml 或 Gradle build.gradle 文件中:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama</artifactId>
</dependency>
implementation 'org.springframework.ai:spring-ai-ollama'
接下来,创建一个 OllamaChatModel 实例,并使用它发送文本生成请求:
var ollamaApi = OllamaApi.builder().build();
var chatModel = OllamaChatModel.builder()
.ollamaApi(ollamaApi)
.defaultOptions(
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> streamResponse = chatModel.stream(
new Prompt("Generate the names of 5 famous pirates."));
OllamaChatOptions 提供了所有聊天请求的配置选项,包括模型、温度等参数。
底层 OllamaApi 客户端
OllamaApi 提供了一个轻量级的 Java 客户端,用于访问 Ollama 聊天完成 API。
下图展示了 OllamaApi 的聊天接口及构建模块示意图:

OllamaApi 属于低级别 API,不建议直接使用。推荐使用 OllamaChatModel。以下是一个简单的示例,展示如何以编程方式使用该 API:
OllamaApi ollamaApi = new OllamaApi("YOUR_HOST:YOUR_PORT");
// 同步请求
var request = ChatRequest.builder("orca-mini")
.stream(false) // 非流式
.messages(List.of(
Message.builder(Role.SYSTEM)
.content("You are a geography teacher. You are talking to a student.")
.build(),
Message.builder(Role.USER)
.content("What is the capital of Bulgaria and what is the size? "
+ "What is the national anthem?")
.build()))
.options(OllamaChatOptions.builder().temperature(0.9).build())
.build();
ChatResponse response = ollamaApi.chat(request);
// 流式请求
var request2 = ChatRequest.builder("orca-mini")
.stream(true) // 流式
.messages(List.of(
Message.builder(Role.USER)
.content("What is the capital of Bulgaria and what is the size? "
+ "What is the national anthem?")
.build()))
.options(OllamaChatOptions.builder().temperature(0.9).build().toMap())
.build();
Flux<ChatResponse> streamingResponse = ollamaApi.streamingChat(request2);
这个示例展示了如何使用 OllamaApi 发起同步和流式聊天请求,并通过 OllamaChatOptions 配置温度等参数。