收藏本站,收获最前沿的人工智能与编程资讯!!

Spring AI 使用 Docker Model Runner

技术文档 17℃ 0

Docker Model Runner 是一款人工智能推理引擎,提供来自各类服务商的丰富模型。

Spring AI 通过复用已有的 OpenAI 对话客户端,实现了与 Docker Model Runner 的集成。使用时需将基础 URL 设置为 localhost:12434/engines,并选择提供的大语言模型之一。

可查看 DockerModelRunnerWithOpenAiChatModelIT.java 测试文件,了解 Spring AI 结合 Docker Model Runner 的使用示例。

前提条件

下载适用于 Mac 的 Docker Desktop 4.40.0 版本。

通过以下任一方式启用 Model Runner:

方式一:

执行命令启用 Model Runner:docker desktop enable model-runner --tcp 12434

将基础地址设置为:localhost:12434/engines

方式二:

执行命令启用 Model Runner:docker desktop enable model-runner

使用 Testcontainers,并按如下方式配置基础地址:

@Container
private static final DockerModelRunnerContainer DMR = new DockerModelRunnerContainer("alpine/socat:1.7.4.3-r0");

@Bean
public OpenAiApi chatCompletionApi() {
	var baseUrl = DMR.getOpenAIEndpoint();
	return OpenAiApi.builder().baseUrl(baseUrl).apiKey("test").build();
}

你可以阅读《使用 Docker 本地运行大语言模型》技术博客,了解更多 Docker Model Runner 相关信息。

自动配置

自 1.0.0.M7 版本起,Spring AI 启动器模块的构件 ID 已重新命名。依赖名称需遵循更新后的命名规范,适用于模型、向量数据库和 MCP 启动器。更多信息请参考升级说明。

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秒
spring.ai.retry.backoff.multiplier退避间隔乘数5
spring.ai.retry.backoff.max-interval最大退避时长3分钟
spring.ai.retry.on-client-errors若为 false,抛出 NonTransientAiException 异常,不重试 4xx 客户端错误false
spring.ai.retry.exclude-on-http-codes禁止触发重试的 HTTP 状态码列表
spring.ai.retry.on-http-codes允许触发重试的 HTTP 状态码列表

连接属性

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

属性描述默认值
spring.ai.openai.base-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可选覆盖基础地址,必须设置为 localhost:12434/engines-
spring.ai.openai.chat.api-key可选覆盖 API 密钥-
spring.ai.openai.chat.options.model使用的大语言模型-
spring.ai.openai.chat.options.temperature采样温度,控制生成内容的创造性,值越高越随机,越低越精准0.8
spring.ai.openai.chat.options.frequencyPenalty-2.0~2.0,正值降低重复语句概率0.0f
spring.ai.openai.chat.options.maxTokens生成最大令牌数,受模型上下文长度限制-
spring.ai.openai.chat.options.n单条输入生成的结果数量,建议设为1节约成本1
spring.ai.openai.chat.options.presencePenalty-2.0~2.0,正值提升新话题生成概率-
spring.ai.openai.chat.options.responseFormat输出格式,{"type": "json_object"} 启用 JSON 模式-
spring.ai.openai.chat.options.seed测试版功能,指定后尽力保证结果可复现-
spring.ai.openai.chat.options.stop最多4个停止生成的序列-
spring.ai.openai.chat.options.topP核采样,替代温度采样,建议只调整其一-
spring.ai.openai.chat.options.tools模型可调用的工具列表,目前仅支持函数-
spring.ai.openai.chat.options.toolChoice控制模型调用函数,none/auto/指定函数无函数时为none,有函数时为auto
spring.ai.openai.chat.options.user终端用户唯一标识,用于监控滥用-
spring.ai.openai.chat.options.stream-usage仅流式,添加令牌用量统计分片false
spring.ai.openai.chat.options.tool-names单次请求启用的工具名称列表-
spring.ai.openai.chat.options.tool-callbacks向对话模型注册的工具回调-
spring.ai.openai.chat.options.internal-tool-execution-enabledtrue:Spring AI 内部处理工具调用;false:交由客户端处理true

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

运行时选项

OpenAiChatOptions.java 提供模型、温度、频率惩罚等配置。

启动时可通过构造方法或配置文件设置默认选项。

运行时可覆盖默认配置,示例:

ChatResponse response = chatModel.call(
    new Prompt(
        "生成5位著名海盗的名字。",
        OpenAiChatOptions.builder()
            .model("ai/gemma3:4B-F16")
        .build()
    ));

除了模型专用的 OpenAiChatOptions,也可使用通用 ChatOptions。

函数调用

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

你可以向对话模型注册自定义 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("阿姆斯特丹和巴黎的天气如何?")
                .functions("weatherFunction") // 通过Bean名称引用
                .call()
                .content();

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

    @Bean
    @Description("获取指定地点的天气")
    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,预期返回:阿姆斯特丹当前气温20摄氏度,巴黎当前气温25摄氏度。

阅读 OpenAI 函数调用文档了解更多。

示例控制器

创建新 Spring Boot 项目,添加 spring-ai-starter-model-openai 依赖。

在 src/main/resources 下添加 application.properties 配置:

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 不支持嵌入向量,需禁用
spring.ai.openai.embedding.enabled=false

简单控制器示例:

@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 = "给我讲个笑话") String message) {
        return Map.of("generation", this.chatModel.call(message));
    }

    @GetMapping("/ai/generateStream")
	public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "给我讲个笑话") String message) {
        Prompt prompt = new Prompt(new UserMessage(message));
        return this.chatModel.stream(prompt);
    }
}

相关推荐