Spring AI Alibaba 接入 OpenAI 兼容协议第三方大模型实战

Spring AI Alibaba 接入 OpenAI 兼容协议第三方大模型实战

本文记录在 Spring AI Alibaba 项目中,以 OpenAI 兼容协议接入第三方大模型(以京东云 AI 为例)的完整过程,包含踩坑记录和解决方案。


背景

Spring AI Alibaba 是阿里云基于 Spring AI 构建的 Java AI 应用开发框架,原生集成 DashScope(通义千问等)。但在实际业务中,我们有时需要接入其他厂商提供的大模型服务。

好消息是:越来越多的大模型 API 提供商(京东云、DeepSeek、Moonshot、vLLM 等)都兼容 OpenAI 的接口协议,只需切换 base-urlapi-key,就能通过 spring-ai-starter-model-openai 无缝接入,无需修改业务代码。


技术栈

组件 版本
Java 17
Spring Boot 3.4.5
Spring AI BOM 1.1.2
模型服务 京东云 AI(OpenAI 兼容协议)

⚠️ 重要spring-ai 1.1.2 基于 Spring Framework 6.x 编译,不兼容 Spring Boot 4.x(Spring Framework 7.x)。若你的项目使用 Spring Boot 4.x,需降级至 Spring Boot 3.4.x。


一、pom.xml 配置

1.1 指定 Spring Boot 版本

xml 复制代码
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.4.5</version>
    <relativePath/>
</parent>

1.2 引入 Spring AI BOM

<dependencyManagement> 中通过 BOM 统一管理 Spring AI 版本,无需在每个依赖上单独写版本号:

xml 复制代码
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>1.1.2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

1.3 添加 OpenAI Starter 依赖

xml 复制代码
<dependencies>
    <!-- OpenAI 兼容协议 Starter,版本由 BOM 管理 -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-model-openai</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

⚠️ 命名变更 :Spring AI 1.0.0-M7 之后,旧名 spring-ai-openai-spring-boot-starter 已废弃 ,1.1.2 中正确的 artifactId 为 spring-ai-starter-model-openai。使用旧名会导致 Maven 依赖解析失败。


二、application.properties 配置

properties 复制代码
spring.application.name=my-ai-app

# ===== 接入京东云 AI(OpenAI 兼容协议)=====
spring.ai.openai.api-key=your-api-key-here
spring.ai.openai.base-url=http://baseurl
spring.ai.openai.chat.options.model=GPT-5.4
spring.ai.openai.chat.options.temperature=0.7

# 若该端点不提供 Embedding 服务,需显式禁用,否则启动报错
spring.ai.model.embedding=none

配置项说明

配置项 说明
spring.ai.openai.base-url 第三方 API 的根地址,替换默认的 https://api.openai.com
spring.ai.openai.api-key 第三方服务的鉴权 Key
spring.ai.openai.chat.options.model 模型名称,使用目标服务支持的模型标识
spring.ai.openai.chat.options.temperature 采样温度,0~2,越高输出越随机
spring.ai.model.embedding=none 禁用 Embedding 自动装配(Spring AI 1.0+ 写法,旧版 spring.ai.openai.embedding.enabled=false 已废弃)

关于 spring.ai.model.embedding=none :旧版的 spring.ai.openai.embedding.enabled=false 在 Spring AI 1.0.0-M7 后已被移除,务必使用新写法。


三、业务代码

Spring AI 提供了高层抽象 ChatClient,配置完成后直接注入即可,无需关心底层是哪家厂商。

java 复制代码
package com.example.ai.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/ai")
public class ChatController {

    private final ChatClient chatClient;

    public ChatController(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }

    @GetMapping("/chat")
    public String chat(@RequestParam(defaultValue = "你好,请介绍一下你自己") String message) {
        return chatClient.prompt()
                .user(message)
                .call()
                .content();
    }
}

ChatClient.Builder 由 Spring AI 自动装配,内部已绑定好 spring.ai.openai.* 的配置,业务代码与具体模型提供商解耦。


四、验证

启动应用:

bash 复制代码
./mvnw spring-boot:run

调用接口:

bash 复制代码
# 默认问候
curl http://localhost:8080/ai/chat

# 自定义问题
curl "http://localhost:8080/ai/chat?message=1%2B1%E7%AD%89%E4%BA%8E%E5%87%A0"

正常响应示例:

bash 复制代码
Hello! How can I help you today?

五、踩坑记录

坑1:Spring Boot 4.x 与 Spring AI 1.1.2 不兼容

现象:

makefile 复制代码
java.lang.ClassNotFoundException: 
org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration

或:

vbnet 复制代码
NoSuchMethodError: 'void org.springframework.http.HttpHeaders.addAll(MultiValueMap)'

原因: Spring AI 1.1.2 编译时依赖 Spring Framework 6.x(对应 Spring Boot 3.x),RestClientAutoConfigurationHttpHeaders 的 API 在 Spring Framework 7.x(Spring Boot 4.x)中已变更或移除。

解决: 将 Spring Boot 降级至 3.4.x。

xml 复制代码
<!-- 改为 3.4.5 -->
<version>3.4.5</version>

坑2:spring-ai-alibaba 与 Spring Boot 4.x 不兼容

现象:

arduino 复制代码
Failed to process import candidates for configuration class 
[com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeAgentAutoConfiguration]

原因: spring-ai-alibaba-starter-dashscopespring-ai-alibaba-agent-framework 同样基于 Spring Boot 3.x 构建,无法在 Spring Boot 4.x 上运行。

解决: 若不需要 DashScope,直接移除这两个依赖,仅保留 spring-ai-starter-model-openai


坑3:Embedding 自动装配失败

现象:

启动时报 Bean 创建失败,与 Embedding 相关。

原因: OpenAI Starter 默认会同时装配 Chat 和 Embedding 客户端,但很多第三方 API 不提供 Embedding 端点。

解决:

properties 复制代码
# 正确写法(Spring AI 1.0+ )
spring.ai.model.embedding=none

# 错误写法(已废弃,无效)
spring.ai.openai.embedding.enabled=false

坑4:artifactId 命名变更

Spring AI 1.0.0-M7 对 starter 进行了重命名:

旧名(已废弃) 新名(1.1.2 使用)
spring-ai-openai-spring-boot-starter spring-ai-starter-model-openai

使用旧名会导致 Maven 无法解析依赖,报 Could not find artifact 错误。


六、兼容其他 OpenAI 协议服务商

同样的配置方式可接入任何 OpenAI 兼容协议的服务:

properties 复制代码
# DeepSeek
spring.ai.openai.base-url=https://api.deepseek.com
spring.ai.openai.chat.options.model=deepseek-chat

# Moonshot(Kimi)
spring.ai.openai.base-url=https://api.moonshot.cn
spring.ai.openai.chat.options.model=moonshot-v1-8k

# 本地 Ollama(OpenAI 兼容模式)
spring.ai.openai.base-url=http://localhost:11434
spring.ai.openai.chat.options.model=llama3

只需修改 base-urlapi-keymodel 三个配置,业务代码零改动。


总结

步骤 关键点
依赖 使用 spring-ai-starter-model-openai,版本由 spring-ai-bom 管理
Spring Boot 版本 必须使用 3.4.x,spring-ai 1.1.2 不兼容 Spring Boot 4.x
配置 覆盖 base-url + api-key + model 即可切换任意兼容服务商
Embedding 不需要时用 spring.ai.model.embedding=none 禁用
业务代码 注入 ChatClient 即可,与模型提供商完全解耦

Spring AI 的 OpenAI 兼容协议支持极大降低了厂商锁定风险,在不修改业务代码的前提下可以灵活切换或对比不同模型服务,是生产环境多模型策略的理想方案。

相关推荐
李广坤1 分钟前
Agent 记忆系统详解:从"金鱼脑"到"过目不忘"的进化之路
后端
zerozrc020 分钟前
Java 方法调用的底层原理
java·后端
睡觉时不困44226 分钟前
9.命令行通用规律:所有命令的底层语法
后端
Maxkim33 分钟前
把智能体塞进浏览器侧边栏:我在 MV3 里踩的 5 个坑
前端·后端
XuCoder35 分钟前
面试官:MySQL 索引是什么?这道题答全的人真不多
后端
特立独行的猫a36 分钟前
我用 Rust + Tauri 2 复刻了 N_m3u8DL-CLI:一个 m3u8 多线程下载器
开发语言·后端·rust·m3u8·视频下载器·m3u8dl-cli
月光有害37 分钟前
理解 Spring 依赖注入:从构造器注入到集合与条件 Bean
java·后端·spring
对象存储与RustFS39 分钟前
大文件传到 48 GiB 就断:S3 分片上传的参数怎么算,以及那些没人清的残片
后端·rust·开源
foggyprojects41 分钟前
客户说“销售额”,系统怎样落到订单含税金额或开票含税销售额?
后端
念何架构之路1 小时前
路由注册:RouterGroup(routergroup.go)
开发语言·后端·golang