Ollama 聊天
通过 Ollama,你可以在本地运行各种大型语言模型(LLMs)并从中生成文本。Spring AI 通过 OllamaChatModel
API 支持 Ollama 的聊天完成功能。
Ollama 还提供了一个与 OpenAI API 兼容的端点。OpenAI API 兼容性部分解释了如何使用 Spring AI OpenAI 连接到 Ollama 服务器。
先决条件
首先,你需要访问一个 Ollama 实例。有几种选择,包括以下几种:
-
在本地机器上下载并安装 Ollama。
-
通过 Testcontainers 配置并运行 Ollama。
-
通过 Kubernetes Service Bindings 绑定到 Ollama 实例。
你可以从 Ollama 模型库 中拉取你想要在应用程序中使用的模型:
ollama pull <model-name>
你也可以拉取成千上万的免费 GGUF Hugging Face 模型:
ollama pull hf.co/<username>/<model-repository>
或者,您可以启用自动下载任何所需模型的选项:自动拉取模型。
自动配置
Spring AI 为 Ollama 聊天集成提供了 Spring Boot 自动配置。要启用它,请将以下依赖项添加到项目的 Maven pom.xml
或 Gradle build.gradle
构建文件中:
- Maven
- Gradle
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>
dependencies {
implementation 'org.springframework.ai:spring-ai-ollama-spring-boot-starter'
}
:::提示
请参考依赖管理部分,将 Spring AI BOM 添加到你的构建文件中。
:::
基础属性
前缀 spring.ai.ollama
是用于配置与 Ollama 连接的属性前缀。
Property | 描述 | 默认值 |
---|---|---|
spring.ai.ollama.base-url | Ollama API 服务器运行的基础 URL。 | [localhost:11434](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.ollama.chat.options
是用于配置 Ollama 聊天模型的属性前缀。它包括 Ollama 请求(高级)参数,如 model
、keep-alive
和 format
,以及 Ollama 模型的 options
属性。
以下是 Ollama 聊天模型的高级请求参数:
属性 | 描述 | 默认值 |
---|---|---|
spring.ai.ollama.chat.enabled | 启用 Ollama 聊天模型。 | true |
spring.ai.ollama.chat.options.model | 使用的支持模型的名称。 | mistral |
spring.ai.ollama.chat.options.format | 返回响应的格式。目前唯一接受的值是 json | - |
spring.ai.ollama.chat.options.keep_alive | 控制模型在请求后保持在内存中的时间 | 5m |
其余的 options
属性基于 Ollama 有效参数和值 和 Ollama 类型。默认值基于 Ollama 类型默认值。
属性 | 描述 | 默认值 |
---|---|---|
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 表示 NumGPU 应动态设置。 | -1 |
spring.ai.ollama.chat.options.main-gpu | 当使用多个 GPU 时,此选项控制用于小张量的 GPU,因为跨所有 GPU 拆分计算的开销不值得。该 GPU 将使用稍多的 VRAM 来存储临时结果的暂存缓冲区。 | 0 |
spring.ai.ollama.chat.options.low-vram | - | false |
spring.ai.ollama.chat.options.f16-kv | - | true |
spring.ai.ollama.chat.options.logits-all | 返回所有 token 的 logits,而不仅仅是最后一个。要使 completions 返回 logprobs,必须为 true。 | - |
spring.ai.ollama.chat.options.vocab-only | 仅加载词汇表,不加载权重。 | - |
spring.ai.ollama.chat.options.use-mmap | 默认情况下,模型被映射到内存中,这允许系统根据需要仅加载模型的必要部分。然而,如果模型大于你的总 RAM 量,或者你的系统可用内存不足,使用 mmap 可能会增加页面调出的风险,从而对性能产生负面影响。禁用 mmap 会导致加载时间变慢,但如果不使用 mlock,可能会减少页面调出。请注意,如果模型大于总 RAM 量,关闭 mmap 将完全阻止模型加载。 | null |
spring.ai.ollama.chat.options.use-mlock | 将模型锁定在内存中,防止其在内存映射时被交换出去。这可以提高性能,但通过需要更多 RAM 来运行并可能减慢加载时间,从而牺牲了内存映射的一些优势。 | false |
spring.ai.ollama.chat.options.num-thread | 设置计算期间使用的线程数。默认情况下,Ollama 会检测此值以获得最佳性能。建议将此值设置为系统具有的物理 CPU 核心数(而不是逻辑核心数)。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 | 减少生成无意义文本的概率。较高的值(例如 100)将提供更多样化的答案,而较低的值(例如 10)将更加保守。 | 40 |
spring.ai.ollama.chat.options.top-p | 与 top-k 一起使用。较高的值(例如 0.95)将导致更多样化的文本,而较低的值(例如 0.5)将生成更加集中和保守的文本。 | 0.9 |
spring.ai.ollama.chat.options.tfs-z | 使用尾自由采样来减少输出中不太可能的 token 的影响。较高的值(例如 2.0)将更显著地减少影响,而值为 1.0 则禁用此设置。 | 1.0 |
spring.ai.ollama.chat.options.typical-p | - | 1.0 |
spring.ai.ollama.chat.options.repeat-last-n | 设置模型回溯多远以防止重复。(默认值:64,0 = 禁用,-1 = num_ctx) | 64 |
spring.ai.ollama.chat.options.temperature | 模型的温度。增加温度将使模型的回答更具创造性。 | 0.8 |
spring.ai.ollama.chat.options.repeat-penalty | 设置对重复的惩罚力度。较高的值(例如 1.5)将更强烈地惩罚重复,而较低的值(例如 0.9)将更加宽容。 | 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,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 | 设置停止序列。当遇到此模式时,LLM 将停止生成文本并返回。可以通过在 modelfile 中指定多个单独的 stop 参数来设置多个停止模式。 | - |
spring.ai.ollama.chat.options.functions | 函数列表,按名称标识,以在单个提示请求中启用函数调用。这些名称的函数必须存在于 functionCallbacks 注册表中。 | - |
spring.ai.ollama.chat.options.proxy-tool-calls | 如果为 true,Spring AI 将不会在内部处理函数调用,而是将它们代理给客户端。然后客户端负责处理函数调用,将其分派给适当的函数并返回结果。如果为 false(默认值),Spring AI 将在内部处理函数调用。仅适用于支持函数调用的聊天模型 | false |
所有以 spring.ai.ollama.chat.options
为前缀的属性都可以通过在 Prompt
调用中添加请求特定的运行时选项来在运行时进行覆盖。
运行时选项
OllamaOptions.java 类提供了模型配置,例如要使用的模型、温度等。
在启动时,默认选项可以通过 OllamaChatModel(api, options)
构造函数或 spring.ai.ollama.chat.options.*
属性进行配置。
在运行时,您可以通过向 Prompt
调用添加新的、特定于请求的选项来覆盖默认选项。例如,要为特定请求覆盖默认模型和温度设置:
ChatResponse response = chatModel.call(
new Prompt(
"Generate the names of 5 famous pirates.",
OllamaOptions.builder()
.model(OllamaModel.LLAMA3_1)
.temperature(0.4)
.build()
));
除了特定模型的 OllamaOptions 外,你还可以使用一个可移植的 ChatOptions 实例,该实例可以通过 ChatOptionsBuilder#builder() 创建。
自动拉取模型
Spring AI Ollama 可以在您的 Ollama 实例中缺少模型时自动拉取模型。这一特性在开发和测试以及将应用程序部署到新环境时特别有用。
你也可以按名称拉取数千个免费的 GGUF Hugging Face 模型。
有三种拉取模型的策略:
-
always
(定义在PullModelStrategy.ALWAYS
中):始终拉取模型,即使它已经存在。适用于确保使用模型的最新版本。 -
when_missing
(定义在PullModelStrategy.WHEN_MISSING
中):仅在模型不存在时拉取。这可能导致使用较旧版本的模型。 -
never
(定义在PullModelStrategy.NEVER
中):从不自动拉取模型。
由于下载模型时可能存在延迟,不建议在生产环境中使用自动拉取功能。相反,请考虑提前评估并预下载所需的模型。
所有通过配置属性和默认选项定义的模型都可以在启动时自动拉取。您可以使用配置属性来配置拉取策略、超时和最大重试次数:
spring:
ai:
ollama:
init:
pull-model-strategy: always
timeout: 60s
max-retries: 1
应用程序在 Ollama 中所有指定的模型都可用之前,不会完成初始化。根据模型大小和互联网连接速度,这可能会显著减慢应用程序的启动时间。
你可以在启动时初始化额外的模型,这对于在运行时动态使用的模型非常有用:
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
此配置将对除聊天模型之外的所有模型应用拉取策略。
函数调用
你可以向 OllamaChatModel
注册自定义的 Java 函数,并让 Ollama 模型智能地选择输出一个包含参数的 JSON 对象,以调用一个或多个已注册的函数。这是一种强大的技术,用于将 LLM 的能力与外部工具和 API 连接起来。了解更多关于 Ollama 函数调用 的信息。
你需要 Ollama 0.2.8 或更高版本来使用函数调用功能,并且需要 Ollama 0.4.6 或更高版本来在流模式下使用这些功能。
多模态
多模态(Multimodality)指的是模型同时理解和处理来自多种来源信息的能力,这些信息包括文本、图像、音频以及其他数据格式。
Ollama 中支持多模态的一些模型包括 LLaVa 和 bakllava(查看完整列表)。更多详细信息,请参阅 LLaVA: Large Language and Vision Assistant。
Ollama 的 Message API 提供了一个 "images" 参数,用于将一组 base64 编码的图像与消息一起传递。
以下是摘自 OllamaChatModelMultimodalIT.java 的一个简单代码示例,展示了用户文本与图像的融合。
var imageResource = new ClassPathResource("/multimodal.test.png");
var userMessage = new UserMessage("Explain what do you see on this picture?",
new Media(MimeTypeUtils.IMAGE_PNG, this.imageResource));
ChatResponse response = chatModel.call(new Prompt(this.userMessage,
OllamaOptions.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 允许你使用 OllamaOptions
构建器以编程方式配置响应格式。
使用聊天选项构建器
你可以通过 OllamaOptions
构建器以编程方式设置响应格式,如下所示:
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",
OllamaOptions.builder()
.withModel(OllamaModel.LLAMA3_2.getName())
.withFormat(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",
OllamaOptions.builder()
.withModel(OllamaModel.LLAMA3_2.getName())
.withFormat(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,…)
注解来生成一个准确标记字段为 required
的 schema。虽然这对于 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
。
查看 OllamaWithOpenAiChatModelIT.java 测试,了解如何在 Spring AI OpenAI 上使用 Ollama 的示例。
HuggingFace 模型
Ollama 可以直接访问所有 GGUF Hugging Face 聊天模型。你可以通过名称拉取这些模型:ollama pull hf.co/<username>/<model-repository>
或者配置自动拉取策略:自动拉取模型:
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-ollama-spring-boot-starter
添加到你的 pom(或 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 服务器 URL。
:::
这将创建一个 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);
}
}
手动配置
如果你不想使用 Spring Boot 的自动配置,你可以在应用程序中手动配置 OllamaChatModel
。OllamaChatModel 实现了 ChatModel
和 StreamingChatModel
,并使用 Low-level OllamaApi Client 来连接 Ollama 服务。
要使用它,请将 spring-ai-ollama
依赖添加到项目的 Maven pom.xml
或 Gradle build.gradle
构建文件中:
- Maven
- Gradle
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama</artifactId>
</dependency>
dependencies {
implementation 'org.springframework.ai:spring-ai-ollama'
}
请参考依赖管理部分,将 Spring AI BOM 添加到您的构建文件中。
spring-ai-ollama
依赖还提供了对 OllamaEmbeddingModel
的访问。有关 OllamaEmbeddingModel
的更多信息,请参阅 Ollama 嵌入模型 部分。
接下来,创建一个 OllamaChatModel
实例,并使用它来发送文本生成请求:
var ollamaApi = new OllamaApi();
var chatModel = new OllamaChatModel(this.ollamaApi,
OllamaOptions.create()
.model(OllamaOptions.DEFAULT_MODEL)
.temperature(0.9));
ChatResponse response = this.chatModel.call(
new Prompt("Generate the names of 5 famous pirates."));
// Or with streaming responses
Flux<ChatResponse> response = this.chatModel.stream(
new Prompt("Generate the names of 5 famous pirates."));
OllamaOptions
提供了所有聊天请求的配置信息。
低级 OllamaApi 客户端
OllamaApi 为 Ollama Chat Completion API Ollama Chat Completion API 提供了一个轻量级的 Java 客户端。
以下类图展示了 OllamaApi
的聊天接口和构建模块:
OllamaApi
是一个底层 API,不建议直接使用。请使用 OllamaChatModel
代替。
以下是一个简单的代码片段,展示了如何以编程方式使用 API:
OllamaApi ollamaApi = new OllamaApi("YOUR_HOST:YOUR_PORT");
// Sync request
var request = ChatRequest.builder("orca-mini")
.stream(false) // not streaming
.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(OllamaOptions.create().temperature(0.9))
.build();
ChatResponse response = this.ollamaApi.chat(this.request);
// Streaming request
var request2 = ChatRequest.builder("orca-mini")
.ttream(true) // streaming
.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(OllamaOptions.create().temperature(0.9).toMap())
.build();
Flux<ChatResponse> streamingResponse = this.ollamaApi.streamingChat(this.request2);
章节摘要
📄️ Ollama 函数调用(已弃用)
你可以向 OllamaChatModel 注册自定义的 Java 函数,并让部署的 Ollama 模型智能选择输出一个包含参数调用的 JSON 对象,以调用一个或多个已注册的函数。这使得你可以将 LLM 的能力与外部工具和 API 连接起来。带有 Tools 标签的 Ollama 模型(参见完整列表)经过训练,能够检测何时应调用函数,并以符合函数签名的 JSON 格式进行响应。