Docker Model Runner

本站(springdoc.cn)中的内容来源于 spring.io ,原始版权归属于 spring.io。由 springdoc.cn 进行翻译,整理。可供个人学习、研究,未经许可,不得进行任何转载、商用或与之相关的行为。 商标声明:Spring 是 Pivotal Software, Inc. 在美国以及其他国家的商标。

Docker Model Runner 是一个 AI 推理引擎,提供来自 多个供应商 的多样化模型。

Spring AI 通过复用现有的 OpenAI 后端 ChatClient 与 Docker Model Runner 集成。需将基础URL设置为 localhost:12434/engines 并选择提供的 LLM 模型 之一。

查看 DockerModelRunnerWithOpenAiChatModelIT.java 测试类,获取 Spring AI 与 Docker Model Runner 结合使用的示例。

先决条件

  • 下载 Mac 版 Docker Desktop 4.40.0。

选择以下任一选项启用 Model Runner:

选项 1:

选项 2:

  • 启用 Model Runner:docker desktop enable model-runner

  • 使用 Testcontainers 并如下设置基础 base-url:

@Container
private static final SocatContainer socat = new SocatContainer().withTarget(80, "model-runner.docker.internal");

@Bean
public OpenAiApi chatCompletionApi() {
	var baseUrl = "http://%s:%d/engines".formatted(socat.getHost(), socat.getMappedPort(80));
	return OpenAiApi.builder().baseUrl(baseUrl).apiKey("test").build();
}

You can learn more about the Docker Model Runner by reading the Run LLMs Locally with Docker blog post.

自动配置

自 1.0.0.M7 版本起,Spring AI starter 模块的构件 ID 已重命名。依赖名称现应遵循更新后的模型、向量存储和 MCP starter 命名规范。更多信息请参阅 升级说明

Spring AI 为 OpenAI 聊天客户端提供 Spring Boot 自动配置。要启用该功能,请将以下依赖添加到项目的 Maven 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'
}
请参阅 依赖管理 章节将 Spring AI BOM 添加到你的构建文件。

聊天属性

重试属性

前缀 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,则抛出 NonTransientAiException,且不对 4xx 客户端错误代码尝试重试

false

spring.ai.retry.exclude-on-http-codes

不应触发重试的 HTTP 状态码列表(例如用于抛出 NonTransientAiException

empty

spring.ai.retry.on-http-codes

应触发重试的 HTTP 状态码列表(例如用于抛出 TransientAiException

empty

连接属性

前缀 spring.ai.openai 用于配置连接至 OpenAI 的属性参数。

属性 说明 默认值

spring.ai.openai.base-url

连接URL必须设置为:hub.docker.com/u/ai

-

spring.ai.openai.api-key

任何字符串

-

配置属性

聊天自动配置的启用/禁用现在通过顶级属性 spring.ai.model.chat 配置:

  • 启用:spring.ai.model.chat=openai(默认启用)

  • 禁用:spring.ai.model.chat=none(或任何非 openai 的值)

此项变更为支持应用中配置多模型。

前缀 spring.ai.openai.chat 用于配置 OpenAI 聊天模型实现的属性参数。

属性 说明 默认值

spring.ai.openai.chat.enabled (已移除且不再有效)

启用 OpenAI 聊天模型

true

spring.ai.model.chat

启用 OpenAI 聊天模型

openai

spring.ai.openai.chat.base-url

可选覆盖 spring.ai.openai.base-url 以提供聊天专用 URL,必须设置为:localhost:12434/engines

-

spring.ai.openai.chat.api-key

可选覆盖 spring.ai.openai.api-key 以提供聊天专用的 API Key

-

spring.ai.openai.chat.options.model

要使用的 LLM 模型

-

spring.ai.openai.chat.options.temperature

采样温度值,用于控制生成内容的表观创造力。数值越高输出越随机,数值越低结果越集中且确定。不建议在同一补全请求中同时修改 temperature 和 top_p 参数,因两者的交互作用难以预测

0.8

spring.ai.openai.chat.options.frequencyPenalty

介于 -2.0 到 2.0 之间的数值。正值会根据 Token 在已生成文本中的现有频率进行惩罚,从而降低模型逐字重复相同内容的可能性

0.0f

spring.ai.openai.chat.options.maxTokens

聊天补全中生成的最大 Token 数量。输入 Token 和生成 Token 的总长度受模型上下文长度限制

-

spring.ai.openai.chat.options.n

为每条输入消息生成的聊天补全选项数量。请注意:费用将基于所有选项生成的 Token 总数计算。保持 n=1 可最小化成本。

1

spring.ai.openai.chat.options.presencePenalty

介于 -2.0 到 2.0 之间的数值。正值会根据 Token 是否已在已生成文本中出现进行惩罚,从而提高模型讨论新话题的可能性。

-

spring.ai.openai.chat.options.responseFormat

指定模型输出格式的对象。设置为 { "type": "json_object" } 可启用 JSON 模式,确保模型生成的消息是有效JSON。

-

spring.ai.openai.chat.options.seed

该功能处于 Beta 阶段。若指定种子值,系统将尽力确保确定性采样——相同种子和参数的重复请求应返回相同结果。

-

spring.ai.openai.chat.options.stop

最多可设置 4 个停止序列,当 API 遇到这些序列时将停止生成后续 Token

-

spring.ai.openai.chat.options.topP

温度采样的替代方案——核采样(nucleus sampling),模型仅考虑累计概率达到 top_p 阈值的 token 候选集。例如 0.1 表示仅考虑概率质量排名前 10% 的 Token。通常建议仅调整此参数或 temperature 参数,而非同时修改两者。

-

spring.ai.openai.chat.options.tools

模型可调用的工具列表。当前仅支持函数作为工具类型,用于提供模型可能生成 JSON 输入的函数列表。

-

spring.ai.openai.chat.options.toolChoice

控制模型是否调用函数:none:模型不调用函数,仅生成消息(无函数时的默认值) 。auto:模型可选择生成消息或调用函数(有函数时的默认值) 。指定具体函数(如 {"type": "function", "function": {"name": "my_function"}}):强制模型调用该函数

-

spring.ai.openai.chat.options.user

用于标识终端用户的唯一 ID,可协助 OpenAI 监控和检测滥用行为。

-

spring.ai.openai.chat.options.functions

函数名称列表,用于在单次提示请求中启用函数调用功能。这些名称对应的函数必须已注册在 functionCallbacks 注册表中。

-

spring.ai.openai.chat.options.stream-usage

(仅限流式传输)设置为 true 时,将在流式响应末尾添加包含整个请求 Token 使用统计的额外数据块。该数据块的 choices 字段为空数组,其他所有数据块虽包含 usage 字段但值为 null

false

spring.ai.openai.chat.options.proxy-tool-calls

若为 true,Spring AI 不会内部处理函数调用,而是代理给客户端处理。此时客户端需负责处理函数调用、分派至对应函数并返回结果。若为 false(默认值),Spring AI 将在内部处理函数调用。仅适用于支持函数调用的聊天模型。

false

所有以 spring.ai.openai.chat.options 为前缀的属性,均可通过在 Prompt 调用中添加请求特定的 运行时选项 进行覆盖。

运行时选项

OpenAiChatOptions.java 提供模型配置参数,包括使用的模型名称、温度值(temperature)、频率惩罚系数(frequency penalty)等。

在启动时,默认选项可通过 OpenAiChatModel(api, options) 构造函数或 spring.ai.openai.chat.options.* 属性进行配置。

在运行时,你可以通过向 Prompt 调用添加新的、特定于请求的选项来覆盖默认配置。例如,针对特定请求覆盖默认模型和温度参数:

ChatResponse response = chatModel.call(
    new Prompt(
        "Generate the names of 5 famous pirates.",
        OpenAiChatOptions.builder()
            .model("ai/gemma3:4B-F16")
        .build()
    ));
除了模型专用的 OpenAiChatOptions 外,你还可以使用通过 ChatOptions#builder() 创建的通用 ChatOptions 实例。

函数调用

Docker Model Runner 在选择支持工具/函数调用的模型时可启用该功能。

你可向 ChatModel 注册自定义 Java 函数,使指定模型能智能输出包含参数的 JSON 对象来调用一个或多个注册函数。该技术能有效连接大语言模型能力与外部工具及 API。

工具调用示例

以下是 Spring AI 与 Docker Model Runner 函数调用的简单使用示例:

spring.ai.openai.api-key=test
spring.ai.openai.base-url=http://localhost:12434/engines
spring.ai.openai.chat.options.model=ai/gemma3:4B-F16
@SpringBootApplication
public class DockerModelRunnerLlmApplication {

    public static void main(String[] args) {
        SpringApplication.run(DockerModelRunnerLlmApplication.class, args);
    }

    @Bean
    CommandLineRunner runner(ChatClient.Builder chatClientBuilder) {
        return args -> {
            var chatClient = chatClientBuilder.build();

            var response = chatClient.prompt()
                .user("What is the weather in Amsterdam and Paris?")
                .functions("weatherFunction") // reference by bean name.
                .call()
                .content();

            System.out.println(response);
        };
    }

    @Bean
    @Description("Get the weather in location")
    public Function<WeatherRequest, WeatherResponse> weatherFunction() {
        return new MockWeatherService();
    }

    public static class MockWeatherService implements Function<WeatherRequest, WeatherResponse> {

        public record WeatherRequest(String location, String unit) {}
        public record WeatherResponse(double temp, String unit) {}

        @Override
        public WeatherResponse apply(WeatherRequest request) {
            double temperature = request.location().contains("Amsterdam") ? 20 : 25;
            return new WeatherResponse(temperature, request.unit);
        }
    }
}

在此示例中,当模型需要天气信息时,将自动调用 weatherFunction 这个 Bean 来获取实时天气数据。预期响应为:“The weather in Amsterdam is currently 20 degrees Celsius, and the weather in Paris is currently 25 degrees Celsius.”。

详细了解 OpenAI 函数调用 功能。

示例 Controller

创建 一个新的 Spring Boot 项目,并在 pom(或 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
spring.ai.openai.chat.options.model=ai/gemma3:4B-F16

# Docker Model Runner doesn't support embeddings, so we need to disable them.
spring.ai.openai.embedding.enabled=false

以下是一个简单的 @Controller 类示例,使用该聊天模型进行文本生成:

@RestController
public class ChatController {

    private final OpenAiChatModel chatModel;

    @Autowired
    public ChatController(OpenAiChatModel 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);
    }
}