Ollama 聊天

使用 Ollama,您可以在本地运行各种大型语言模型 (LLM) 并生成文本。Spring AI 支持使用 OllamaChatModel 进行 Ollama 文本生成。

先决条件

您首先需要在本地机器上运行 Ollama。请参阅官方 Ollama 项目 README,开始在本地机器上运行模型。

安装 ollama run llama3 将下载一个 4.7GB 的模型工件。

添加存储库和 BOM

Spring AI 工件发布在 Spring Milestone 和 Snapshot 存储库中。请参阅 存储库 部分,将这些存储库添加到您的构建系统中。

为了帮助进行依赖管理,Spring AI 提供了一个 BOM(物料清单)以确保在整个项目中使用一致版本的 Spring AI。请参阅 依赖管理 部分,将 Spring AI BOM 添加到您的构建系统中。

自动配置

Spring AI 为 Ollama 聊天客户端提供 Spring Boot 自动配置。要启用它,请将以下依赖项添加到项目的 Maven pom.xml 文件中

<dependency>
   <groupId>org.springframework.ai</groupId>
   <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>

或添加到您的 Gradle build.gradle 构建文件中。

dependencies {
    implementation 'org.springframework.ai:spring-ai-ollama-spring-boot-starter'
}
请参阅 依赖管理 部分,将 Spring AI BOM 添加到您的构建文件中。

聊天属性

前缀spring.ai.ollama是用于配置与 Ollama 连接的属性前缀。

属性 描述 默认值

spring.ai.ollama.base-url

Ollama API 服务器运行的基地址。

localhost:11434

前缀spring.ai.ollama.chat.options是用于配置 Ollama 聊天模型的属性前缀。它包含 Ollama 请求(高级)参数,例如modelkeep-aliveformat,以及 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

设置用于生成下一个标记的上下文窗口大小。

2048

spring.ai.ollama.chat.options.num-batch

???

512

spring.ai.ollama.chat.options.num-gqa

Transformer 层中 GQA 组的数量。某些模型需要此参数,例如,llama2:70b 为 8。

1

spring.ai.ollama.chat.options.num-gpu

要发送到 GPU 的层数。在 macOS 上,默认值为 1 以启用 Metal 支持,0 为禁用。这里的 1 表示 NumGPU 应动态设置。

-1

spring.ai.ollama.chat.options.main-gpu

???

-

spring.ai.ollama.chat.options.low-vram

???

false

spring.ai.ollama.chat.options.f16-kv

???

true

spring.ai.ollama.chat.options.logits-all

???

-

spring.ai.ollama.chat.options.vocab-only

???

-

spring.ai.ollama.chat.options.use-mmap

???

true

spring.ai.ollama.chat.options.use-mlock

???

false

spring.ai.ollama.chat.options.num-thread

设置计算过程中使用的线程数。默认情况下,Ollama 会自动检测以获得最佳性能。建议将此值设置为系统中物理 CPU 内核数(而不是逻辑内核数)。0 = 让运行时决定

0

spring.ai.ollama.chat.options.num-keep

???

0

spring.ai.ollama.chat.options.seed

设置用于生成的随机数种子。将其设置为特定数字将使模型对相同的提示生成相同的文本。

-1

spring.ai.ollama.chat.options.num-predict

生成文本时要预测的最大令牌数。(-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

无尾采样用于减少输出中不太可能出现的令牌的影响。较高的值(例如,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 将停止生成文本并返回。可以通过在模型文件中指定多个单独的停止参数来设置多个停止模式。

-

所有以 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.create()
            .withModel("llama2")
            .withTemperature(0.4)
    ));
除了特定于模型的 OllamaOptions 之外,您还可以使用可移植的 ChatOptions 实例,使用 ChatOptionsBuilder#builder() 创建。

多模态

多模态是指模型同时理解和处理来自各种来源的信息的能力,包括文本、图像、音频和其他数据格式。

目前,LLaVabakllava Ollama 模型提供多模态支持。有关更多详细信息,请参阅 LLaVA: 大型语言和视觉助手

Ollama 消息 API 提供一个“图像”参数,用于将 base64 编码的图像列表与消息一起合并。

Spring AI 的 Message 接口通过引入 Media 类型来促进多模态 AI 模型。此类型包含有关消息中媒体附件的数据和详细信息,利用 Spring 的 org.springframework.util.MimeTypejava.lang.Object 来表示原始媒体数据。

以下是从 OllamaChatModelMultimodalIT.java 中摘录的一个简单代码示例,说明了用户文本与图像的融合。

byte[] imageData = new ClassPathResource("/multimodal.test.png").getContentAsByteArray();

var userMessage = new UserMessage("Explain what do you see on this picture?",
        List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageData)));

ChatResponse response = chatModel.call(
    new Prompt(List.of(userMessage), OllamaOptions.create().withModel("llava")));

logger.info(response.getResult().getOutput().getContent());

它以 multimodal.test.png 图像作为输入

Multimodal Test Image

以及文本消息“解释一下你在这张图片上看到了什么?”,并生成类似这样的响应

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.

示例控制器

创建 一个新的 Spring Boot 项目,并将 spring-ai-ollama-spring-boot-starter 添加到您的 pom(或 gradle)依赖项中。

src/main/resources 目录下添加一个 application.properties 文件,以启用和配置 Ollama 聊天模型

spring.ai.ollama.base-url=https://127.0.0.1:11434
spring.ai.ollama.chat.options.model=mistral
spring.ai.ollama.chat.options.temperature=0.7
base-url 替换为您的 Ollama 服务器 URL。

这将创建一个 OllamaChatModel 实现,您可以将其注入到您的类中。以下是一个使用聊天模型进行文本生成的简单 @Controller 类的示例。

@RestController
public class ChatController {

    private final OllamaChatModel chatModel;

    @Autowired
    public ChatController(OllamaChatModel 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 prompt = new Prompt(new UserMessage(message));
        return chatModel.stream(prompt);
    }

}

手动配置

如果您不想使用 Spring Boot 自动配置,可以在您的应用程序中手动配置 OllamaChatModelOllamaChatModel 实现 ChatModelStreamingChatModel,并使用 低级 OllamaApi 客户端 连接到 Ollama 服务。

要使用它,请将 spring-ai-ollama 依赖项添加到您的项目的 Maven pom.xml 文件中

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-ollama</artifactId>
</dependency>

或添加到您的 Gradle build.gradle 构建文件中。

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(ollamaApi,
            OllamaOptions.create()
                .withModel(OllamaOptions.DEFAULT_MODEL)
                .withTemperature(0.9f));

ChatResponse response = chatModel.call(
    new Prompt("Generate the names of 5 famous pirates."));

// Or with streaming responses
Flux<ChatResponse> response = chatModel.stream(
    new Prompt("Generate the names of 5 famous pirates."));

OllamaOptions 提供所有聊天请求的配置信息。

低级 OllamaApi 客户端

OllamaApi 为 Ollama 聊天完成 API 提供了一个轻量级的 Java 客户端 Ollama 聊天完成 API

以下类图说明了 OllamaApi 聊天接口和构建块

OllamaApi Chat Completion API Diagram

这是一个简单的代码片段,展示了如何以编程方式使用 API

OllamaApi 是低级 API,不建议直接使用。请使用 OllamaChatModel 代替。
OllamaApi ollamaApi =
    new OllamaApi("YOUR_HOST:YOUR_PORT");

// Sync request
var request = ChatRequest.builder("orca-mini")
    .withStream(false) // not streaming
    .withMessages(List.of(
            Message.builder(Role.SYSTEM)
                .withContent("You are a geography teacher. You are talking to a student.")
                .build(),
            Message.builder(Role.USER)
                .withContent("What is the capital of Bulgaria and what is the size? "
                        + "What is the national anthem?")
                .build()))
    .withOptions(OllamaOptions.create().withTemperature(0.9f))
    .build();

ChatResponse response = ollamaApi.chat(request);

// Streaming request
var request2 = ChatRequest.builder("orca-mini")
    .withStream(true) // streaming
    .withMessages(List.of(Message.builder(Role.USER)
        .withContent("What is the capital of Bulgaria and what is the size? " + "What is the national anthem?")
        .build()))
    .withOptions(OllamaOptions.create().withTemperature(0.9f).toMap())
    .build();

Flux<ChatResponse> streamingResponse = ollamaApi.streamingChat(request2);