Spring AI 入门实践:Spring AI 图片生成(Image Generation API)

本章节将基于 Spring Boot 3.xSpring AI 框架,通过 Ollama 在本地运行 DeepSeek-R1Qwen3Gemma3 等大型语言模型 (LLM) 并从中生成文本。

前提条件(Prerequisites)

首先,我们需要一个可以访问的 Ollama 实例。有以下几个选择:

然后我们从 Ollama 模型库 中提取想要在应用程序中使用的模型:

ollama pull <model-name>

你还可以下载数千个免费的 GGUF Hugging Face 模型中的任何一个:

ollama pull hf.co/<username>/<model-repository>

或者,您可以启用自动下载任何所需模型的选项:自动拉取模型

获取 Ollama 对话模型

Ollama 模型库提供了很多的模型供我们选择,下面我们选择了,国产的是一个基于大型语言模型的对话系统,支持对话问答、文本生成等功能。

以下是一些推荐的 Ollama Chat 模型:

DeepSeek-R1

DeepSeek-R1 是一种强大的混合专家 (MoE) 语言模型,具有经济的训练和高效的推理特点。在数学、代码和推理任务中,其性能接近领先模型,如 O3 和 Gemini 2.5 Pro。

模型列表
模型名称 大小 上下文长度 输入类型
deepseek-r1:1.5b 1.1GB 128K 文本
deepseek-r1:7b 4.7GB 128K 文本
deepseek-r1:8b 5.2GB 128K 文本
deepseek-r1:14b 9.0GB 128K 文本
deepseek-r1:32b 20GB 128K 文本
deepseek-r1:70b 43GB 128K 文本
deepseek-r1:671b 404GB 160K 文本

使用下面命令,在本地运行一个 8B 的模型:

ollama run deepseek-r1:8b

Qwen3

Qwen3 是 Qwen 系列大语言模型的最新一代,提供了一套全面的密集模型与专家混合(MoE)模型。

Qwen 3 系列是一套全面的密集与专家混合(MoE)模型集合。其旗舰模型 Qwen3-235B-A22B 在编码、数学、通用能力等基准测试中,与 DeepSeek-R1、o1、o3-mini、Grok-3 及 Gemini-2.5-Pro 等其他顶级模型相比,取得了具有竞争力的成绩。此外,小型 MoE 模型 Qwen3-30B-A3B 以十倍激活参数的优势超越了 QwQ-32B,即便是微型模型如 Qwen3-4B,其性能也能与 Qwen2.5-72B-Instruct 相媲美。

  • 在数学、代码生成和常识逻辑推理方面,其推理能力显著增强,超越了之前的 QwQ(思考模式下)和 Qwen2.5 指令模型(非思考模式下)。
  • 卓越的人类偏好对齐,擅长创意写作、角色扮演、多轮对话及指令遵循,以提供更自然、引人入胜且沉浸式的对话体验。
  • 精通智能体能力,实现与外部工具在思考与无思考模式下的精准集成,并在复杂的基于智能体的任务中达到开源模型中的领先性能。
  • 支持 100 多种语言和方言,具备强大的多语言指令遵循和翻译能力。

我们可以通过从下面模型列表中选择适合自己的模型运行:

模型列表
模型名称 大小 上下文长度 输入类型
qwen3:0.6b 523MB 40K 文本
qwen3:1.7b 1.4GB 40K 文本
qwen3:4b 2.5GB 256K 文本
qwen3:8b 5.2GB 40K 文本
qwen3:14b 9.3GB 40K 文本
qwen3:30b 19GB 256K 文本
qwen3:32b 20GB 40K 文本
qwen3:235b 142GB 256K 文本

使用下面命令,在本地运行一个 8B 的模型:

ollama run qwen3:8b

Google Gemma3

Gemma 是谷歌基于 Gemini 技术打造的一款轻量级模型系列。Gemma 3 模型具备多模态处理能力,能够同时处理文本和图像,并拥有 128K 的上下文窗口,支持超过 140 种语言。该系列模型提供 270M、1B、4B、12B 和 27B 等不同参数规模,在问答、摘要和推理等任务中表现卓越,其紧凑的设计使其能够在资源有限的设备上轻松部署。

模型列表
模型名称 大小 上下文长度 输入类型
gemma3:270m 292MB 32k 文本
gemma3:1b 815MB 32k 文本
gemma3:4b 3.3GB 128K 文本、图像
gemma3:12b 8.1GB 128K 文本、图像
gemma3:27b 17GB 128K 文本、图像

使用下面命令,在本地运行一个 4B 的模型:

ollama run gemma3:4b

添加 Spring AI 依赖

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

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

或者,在你的 Gradle 构建文件 build.gradle 中添加:

dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-ollama'
}

基础属性(Base Properties)

前缀是 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 除默认配置外需要初始化的额外模型列表 []

聊天属性(Chat Properties)

前缀 spring.ai.ollama.chat.options 的属性是配置 Ollama 聊天模型的属性。它包括 Ollama 请求 (高级) 参数,如 modelkeep-aliveformat ,以及 Ollama 模型选项属性。

属性 描述 默认值
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 类型。默认值基于 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),而不仅仅是最后一个。要使补全功能返回对数概率(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 来运行并可能减慢加载时间(因为模型会加载到 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.min-p top_p 的替代方案,旨在确保质量和多样性的平衡。参数 p 代表一个 token 被考虑的最小概率,相对于最可能 token 的概率。例如,p=0.05 且最可能 token 的概率为 0.9 时,值小于 0.045 的逻辑值将被过滤掉。 0.0
spring.ai.ollama.chat.options.tfs-z 使用尾部自由采样(Tail-free sampling)来减少输出中较低概率 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 采样以控制困惑度(perplexity)。(默认值: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

运行时选项(Runtime Options )

Ollamaoptions.java 提供模型配置,例如要使用的 temperature、maxToken、topP 等。

在启动时,可以使用 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()
    ));

自动拉取模型(Auto-pulling Models)

当模型在 Ollama 实例中不可用时,Spring AI 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

这种配置将将拉取策略应用于除聊天模型外的所有模型。

工具 / 功能调用(Tool/Function Calling)

您可以使用 OllamaChatModel 注册自定义 Java 函数,并让 OllamaModel 智能地选择输出一个包含参数的 JSON 对象来调用一个或多个注册的函数。这是一种强大的技术,可以将 LLM 功能与外部工具和 API 连接起来。详细了解工具调用。

多模态(Multimodal )

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

在 Ollama 中提供的一些支持多模态的模型包括 LLaVABakLLaVA (参见完整列表)。有关更多详细信息,请参阅 LLaVA: 大语言和视觉助手

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

Spring AI 的消息接口通过引入媒体类型来促进多模态 AI 模型。这种类型利用 Spring 的 org.springframework.util.MimeTypeorg.springframework.core.io.Resource 来处理原始媒体数据,包含消息中与媒体附件相关的数据和细节。

下面是一个直观的代码示例,摘自 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.

结构化输出(tructured Outputs)

Ollama 提供自定义结构化输出 API, 确保您的模型生成的响应严格符合您提供的 JSON Schema。除了现有的 Spring AI 模型无关的结构化输出转换器外,这些 API 还提供了增强的控制和精度。

配置(Configuration )

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()
            .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",
        OllamaOptions.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);

OpenAI API 兼容性

Ollama 与 OpenAI API 兼容,你可以使用 Spring AI OpenAI 客户端与 Ollama 通话并使用工具。为此,你需要为 Ollama 实例配置 OpenAI 基本 URL:spring.ai.openai.chat.base-url=http://localhost:11434, 并选择其中一个提供的 Ollama 模型:spring.ai.openai.chat.options.model=mistral

HuggingFace 模型

Ollama 可以直接访问所有 GGUF 拥抱面对面聊天模型。你可以按名称拉取任何模型: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

示例控制器(Sample Controller)

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

在 src/main/resources 目录下添加 application.properties 文件,以启用和配置 Hugging Face 聊天模型:

spring:
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        options:
          model: mistral
          temperature: 0.7

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

@RestController
public class ChatController {

    private final OllamaChatModel chatModel;

    @Autowired
    public ChatController(OllamaChatModel chatModel) {
        this.chatModel = chatModel;
    }

    @GetMapping("/ai/generate")
    @Operation(summary = "文本生成")
    public Map<String, Object> generate(@RequestParam(value = "message", defaultValue = "你好!") String message) {
        try {
            String response = chatModel.call(message);
            return Map.of(
                "success", true,
                "generation", response,
                "message", "Generated successfully"
            );
        } catch (Exception e) {
            return Map.of(
                "success", false,
                "error", e.getMessage(),
                "message", "Generation failed"
            );
        }
    }

    @GetMapping("/ai/generateStream")
    public Flux<String> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
        return this.chatModel.stream(message).contextCapture();
    }

}
作者:Jeebiz  创建时间:2024-04-24 00:39
最后编辑:Jeebiz  更新时间:2025-09-28 09:15