前几篇我们分别接入了云端 DeepSeek、OpenAI ChatGPT,还用 Ollama 在本地跑了大模型。今天,我们进入国产大模型的主场——阿里云百炼平台,以及它的 Java 最佳拍档:Spring AI Alibaba

如果你是国内开发者,大概率会遇到这样的场景:公司要求使用国产大模型(合规、数据不出境),而且最好和阿里云已有的基础设施打通。Spring AI Alibaba 正是为这个场景量身打造的框架——它基于 Spring AI 标准构建,深度集成阿里云百炼平台(DashScope),提供对通义千问全系列模型的原生支持。

今天这篇,我们从零开始接入百炼平台,体验 ChatClient 文本对话和多模态图像理解两大核心能力。

一、痛点场景:国产大模型接入的“最后一公里”

先来看看几个真实的开发者困境:

场景一:合规要求

公司项目要求所有数据不出境,必须使用国产大模型。但团队对阿里云百炼的 API 格式不熟悉,担心接入成本高、文档不完善。如果用原始 HTTP 调用,要自己处理签名、Token 管理、重试逻辑,费时费力。

场景二:生态整合

项目已经用了 Spring Cloud Alibaba 全家桶(Nacos、Sentinel、RocketMQ),想在同一个技术栈里接入 AI 能力。如果另起一套 Python 服务,运维成本翻倍。

场景三:多模态需求

产品经理要求做一个“拍照识物”功能——用户上传一张图片,AI 自动识别并描述内容。你可能会想:这得用 Python 的视觉模型吧?Java 能搞吗?

答案都是:能。而且比你想象中简单得多。 Spring AI Alibaba 把百炼平台的能力封装成了标准的 ChatClientChatModel,你用前面几篇学到的任何知识,在这里完全复用。并且通过 withMultiModel(true) 配置,一行开关即可在纯文本与多模态之间切换。

二、核心概念快览

2.1 Spring AI Alibaba 是什么?

Spring AI Alibaba 是阿里云基于 Spring AI 官方标准深度打造的企业级 AI 应用开发框架。它的核心价值在于:一套标准 API,屏蔽不同大模型的底层差异,让 Java 开发者像写 Spring Boot 业务代码一样开发 AI 应用。它的底层兼容 Spring AI 全量 API,无缝对接 Spring Boot、Spring Cloud 微服务生态,并深度整合阿里云灵积 DashScope 平台,原生支持通义千问全系列模型。

简单记忆:Spring AI 定义了“怎么用”的标准,Spring AI Alibaba 提供了“连什么”的落地实现。

2.2 百炼平台(DashScope)

百炼是阿里云推出的一站式大模型服务平台,底层是通义千问系列模型。通过统一的 API,你可以访问文本生成、图像理解、语音合成、视频生成等多种模型能力。Spring AI Alibaba 通过 dashscope starter 封装了对百炼平台的访问,你只需要一个 API Key 就能调用所有服务。

2.3 多模态图像理解

“多模态”这个词听起来唬人,其实就是让模型能处理多种类型的信息输入——不只是文字,还有图片、视频、音频等。图像理解是多模态的一个子集,指的是模型能“看懂”图片内容并给出描述。比如给它一张猫的照片,它能告诉你“这是一只橘猫,正趴在沙发上睡觉”。Spring AI Alibaba 通过在 DashScopeChatOptions 中开启 withMultiModal(true) 并将 Media 对象附加到 UserMessage 上来支持多模态输入。

2.4 与 Spring AI 的关系

Spring AI Alibaba 项目和前面几篇用的 Spring AI(开源版)是一脉相承的:

  • Spring AI Alibaba 是 Spring AI 的阿里云实现,底层完全遵循 Spring AI 的 API 规范。
  • 你前面学到的 ChatClientPrompt、流式输出、结构化输出等概念和调用方式,在这里全部通用。
  • 区别只在于依赖和配置:从 spring-ai-starter-model-openai 换成 spring-ai-alibaba-starter-dashscope,从 base-url 换成百炼自动配置。

三、环境准备

3.1 获取百炼 API Key

访问 百炼控制台,用阿里云账号登录。进入“API Key 管理”页面,创建一个新的 API Key。

新用户通常有可观的免费额度,足够学习和测试使用。Key 创建后仅显示一次,务必保存好。

设置环境变量(避免硬编码):

# Mac / Linux
export DASHSCOPE_API_KEY=sk-你的密钥

# Windows PowerShell
$env:DASHSCOPE_API_KEY="sk-你的密钥"

如果使用 IDEA,记得在 Run Configuration 中添加该环境变量。

3.2 Maven 依赖

创建一个新的 Spring Boot 项目(JDK 17+,Spring Boot 3.5.x)。在 pom.xml 中添加 Spring AI Alibaba 的 BOM 和 dashscope starter:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.14</version>
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>spring-ai-alibaba-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>17</java.version>
        <!--
            版本说明(2026 年 5 月):
            Spring AI Alibaba 1.1.2.0 是当前最新稳定版,对应 Spring AI 1.1.2
            请关注 https://github.com/alibaba/spring-ai-alibaba/releases 获取最新版本
        -->
        <spring-ai-alibaba.version>1.1.2.0</spring-ai-alibaba.version>
        <spring-ai.version>1.1.6</spring-ai.version>
    </properties>

    <dependencies>
        <!-- Spring Boot Web Starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring AI Alibaba DashScope Starter:提供百炼平台接入能力 -->
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
            <version>${spring-ai-alibaba.version}</version>
        </dependency>

        <!-- Spring Boot 测试 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!-- Spring AI BOM:统一管理 Spring AI 相关依赖版本 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>${spring-ai.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

依赖注意spring-ai-alibaba-starter-dashscope 内部已经包含了百炼平台的默认 URL 配置,因此在 application.yml 中通常无需配置 base-url,只需要配置 api-key 即可。如果需要自定义连接参数,可以通过 spring.ai.dashscope.connection 相关配置项调整。

3.3 application.yml 配置

spring:
  application:
    name: spring-ai-alibaba-demo

  ai:
    dashscope:
      api-key: ${DASHSCOPE_API_KEY}     # 从环境变量读取
      chat:
        options:
          model: qwen-plus               # 使用通义千问增强版
          temperature: 0.7

# 开发阶段建议开启 DEBUG 日志,方便排查请求/响应内容
logging:
  level:
    com.alibaba.cloud.ai: DEBUG

模型选择说明

百炼平台提供了多个文本模型,按能力和成本排序:

模型名称 特点 适用场景
qwen-turbo 速度快,成本最低 简单对话、文本分类
qwen-plus 效果、速度、成本均衡 日常对话、内容生成(推荐)
qwen-max 最强能力,复杂推理 高质量创作、复杂分析
qwen-vl-max 多模态模型 图像理解、图文分析

日常学习和开发,推荐使用 qwen-plus,性价比最高。如果需要测试多模态功能,需要切换为 qwen-vl-max 等多模态模型。

四、代码实战:文本对话与多模态

4.1 创建 AIChatService

新建 service 包,创建 AIChatService.java

package com.example.demo.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.MimeTypeUtils;
import reactor.core.publisher.Flux;

@Service
public class AIChatService {

    private final ChatClient chatClient;
    private final ChatModel chatModel;  // 注入 ChatModel 以支持多模态配置

    /**
     * 构造器注入 ChatClient 和 ChatModel
     * ChatClient 用于纯文本对话
     * ChatModel 用于需要自定义配置的高级场景(如多模态)
     */
    public AIChatService(ChatClient chatClient, ChatModel chatModel) {
        this.chatClient = chatClient;
        this.chatModel = chatModel;
    }

    // ========== 纯文本对话 ==========

    /**
     * 同步对话
     */
    public String chat(String message) {
        return chatClient
                .prompt()
                .user(message)
                .call()
                .content();
    }

    /**
     * 流式对话(打字机效果)
     */
    public Flux<String> streamChat(String message) {
        return chatClient
                .prompt()
                .user(message)
                .stream()
                .content();
    }

    // ========== 多模态:图像理解 ==========

    /**
     * 图像理解:从 classpath 读取图片并分析
     * 使用 ChatModel 而非 ChatClient,因为需要自定义 DashScopeChatOptions
     * @param imagePath classpath 下的图片路径,如 "/images/cat.jpg"
     * @param question 关于图片的问题,如 "描述这张图片"
     */
    public String understandImage(String imagePath, String question) {
        // 创建自定义 ChatClient(带有多模态配置)
        return ChatClient.create(chatModel)
                .prompt()
                .user(userSpec -> {
                    // 设置文本部分
                    userSpec.text(question);
                    // 附加图片资源
                    userSpec.media(
                            MimeTypeUtils.IMAGE_JPEG,
                            new ClassPathResource(imagePath)
                    );
                })
                .options(com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions
                        .builder()
                        .withModel("qwen-vl-max")     // 切换为多模态模型
                        .withMultiModel(true)          // 开启多模态支持
                        .build())
                .call()
                .content();
    }

    /**
     * 图像理解(通过 URL)
     * @param imageUrl 图片的网络地址
     * @param question 问题
     */
    public String understandImageByUrl(String imageUrl, String question) {
        return ChatClient.create(chatModel)
                .prompt()
                .user(userSpec -> {
                    userSpec.text(question);
                    try {
                        userSpec.media(
                                MimeTypeUtils.IMAGE_PNG,
                                new java.net.URI(imageUrl).toURL()
                        );
                    } catch (Exception e) {
                        throw new RuntimeException("图片 URL 格式错误", e);
                    }
                })
                .options(com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions
                        .builder()
                        .withModel("qwen-vl-max")
                        .withMultiModel(true)
                        .build())
                .call()
                .content();
    }
}

关键点解读

  • 纯文本对话用的就是前面几篇的标准 ChatClient,写法完全一致。
  • 多模态(图像理解)需要用 DashScopeChatOptions 指定多模态模型并开启 withMultiModal(true),然后将图片作为 media 附加到 UserMessage 上。
  • ChatClient.create(chatModel) 手动创建实例来支持自定义 Options,这是相对底层的用法,适用于需要特定模型配置的高级场景。
  • 图片可以通过本地文件(ClassPathResource)或网络 URL 传入。
  • 多模态模型支持 image 和 video 格式,但不同模型的具体支持范围不同。如 qwen-vl-max 支持图片和视频,使用时需要通过 message.getMetadata().put(DashScopeApiConstants.MESSAGE_FORMAT, MessageFormat.VIDEO) 来指定。

4.2 创建 Controller

新建 controller 包,创建 AIController.java

package com.example.demo.controller;

import com.example.demo.service.AIChatService;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

@RestController
public class AIController {

    private final AIChatService chatService;

    public AIController(AIChatService chatService) {
        this.chatService = chatService;
    }

    /**
     * 文本同步对话
     * GET /ai/chat?msg=你好
     */
    @GetMapping("/ai/chat")
    public String chat(@RequestParam(defaultValue = "请用一句话介绍通义千问") String msg) {
        return chatService.chat(msg);
    }

    /**
     * 文本流式对话(SSE)
     * GET /ai/stream?msg=介绍Spring Boot
     */
    @GetMapping(value = "/ai/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamChat(@RequestParam String msg) {
        return chatService.streamChat(msg);
    }

    /**
     * 图像理解(本地图片)
     * GET /ai/vision?question=描述这张图片
     * 需要在 src/main/resources/images/ 下放置测试图片
     */
    @GetMapping("/ai/vision")
    public String vision(@RequestParam(defaultValue = "描述这张图片") String question) {
        return chatService.understandImage("/images/test.jpg", question);
    }

    /**
     * 图像理解(通过 URL)
     * GET /ai/vision-url?imageUrl=图片地址&question=描述这张图片
     */
    @GetMapping("/ai/vision-url")
    public String visionByUrl(
            @RequestParam String imageUrl,
            @RequestParam(defaultValue = "描述这张图片") String question) {
        return chatService.understandImageByUrl(imageUrl, question);
    }
}

4.3 准备测试图片

src/main/resources/images/ 目录下放一张测试图片(如 test.jpg),用于验证图像理解功能。你可以随便找一张照片放进去。

五、运行与演示

5.1 启动应用

确保 DASHSCOPE_API_KEY 环境变量已设置,启动 Spring Boot 应用。

5.2 测试文本对话

浏览器访问:

http://localhost:8080/ai/chat?msg=用一句话介绍阿里云百炼平台

返回类似:

阿里云百炼是一站式大模型服务平台,提供通义千问系列模型的 API 调用、模型微调和应用部署能力。

5.3 测试流式对话

使用 curl 查看打字机效果:

curl -N "http://localhost:8080/ai/stream?msg=用100字介绍Spring AI Alibaba"

你会看到逐字蹦出的文本流。

5.4 测试图像理解

先确保 src/main/resources/images/test.jpg 文件存在,然后浏览器访问:

http://localhost:8080/ai/vision?question=描述这张图片里的内容

如果你测试通过 URL 的图片识别接口:

http://localhost:8080/ai/vision-url?imageUrl=https://example.com/cat.jpg&question=这是什么动物

返回结果类似:

这是一只橘色的猫,正趴在灰色的沙发上睡觉,画面光线柔和,整体氛围很温馨。

六、常见问题与避坑提示

问题一:API Key 不生效或 401 错误

原因:环境变量未正确设置,或 Key 格式错误。

排查

  1. 终端执行 echo $DASHSCOPE_API_KEY(Mac/Linux)或 echo $env:DASHSCOPE_API_KEY(PowerShell)确认变量有值。
  2. IDEA 中需要在 Run Configuration 中手动添加环境变量,它不会自动读取系统终端的环境变量。
  3. 百炼 API Key 的格式通常以 sk- 开头,确认是否完整复制。

问题二:图片上传报错 “url error, please check url”

HTTP 400 - {"code":"InvalidParameter","message":"url error, please check url!"}

这是百炼多模态接口的一个常见问题。Spring AI Alibaba 的多模态功能需要额外配置——必须在 DashScopeChatOptions 中开启 withMultiModal(true),否则百炼会把图片地址当成文本参数处理,导致 URL 解析错误。遇到这个错误时,请检查是否已添加 .withMultiModal(true) 配置。

问题三:模型名称无效

model "xxx" not found

原因:配置的模型名称不在百炼支持的列表中。

解决:登录百炼控制台查看可用模型列表。注意文本模型和多模态模型是分开的:

  • 文本对话用:qwen-turboqwen-plusqwen-max
  • 多模态(图像理解)用:qwen-vl-maxqwen-vl-plus

问题四:接口超时

java.net.SocketTimeoutException: Read timed out

百炼接口在处理长文本或图片时可能需要较长时间。可以在 application.yml 中增加超时配置:

spring:
  ai:
    dashscope:
      chat:
        options:
          timeout: 120s    # 增加超时时间

问题五:多模态模型不支持视频格式

如果你尝试传入视频文件但调用失败,可能是因为当前多模态模型只支持 image 格式。注意 qwen-vl-max 支持图片和视频,但需要通过 message.getMetadata().put(DashScopeApiConstants.MESSAGE_FORMAT, MessageFormat.VIDEO) 来指定视频格式。对于其他多模态模型,请查阅百炼官方文档确认具体支持范围。

七、小结与下一步预告

本篇回顾

  • 理解了 Spring AI Alibaba 的定位:Spring AI 的阿里云落地实现,一套标准 API 打通百炼全系模型。
  • 完成了环境搭建:添加 spring-ai-alibaba-starter-dashscope 依赖,配置 DASHSCOPE_API_KEY
  • 实现了文本对话和流式输出——代码与前面几篇完全一致。
  • 掌握了多模态图像理解:通过 DashScopeChatOptions.withMultiModal(true) 开启多模态,将图片作为 media 附加到消息中。

和前面几篇的呼应

还记得第 3 篇我们说的“改配置,不改代码”吗?从 DeepSeek 到 OpenAI 到 Ollama 再到今天的百炼,你的业务代码始终是:

chatClient.prompt().user(message).call().content();

这正是 Spring AI 生态最核心的价值——让你专注于业务逻辑,而不是模型接入细节。

下一步预告

现在我们已经掌握了文本对话、流式输出、结构化输出和多模态能力。下一篇,我们将构建一个“记得你的聊天机器人”——引入对话记忆(Chat Memory),让 AI 能记住上下文,实现真正的多轮对话。我们会深入 Spring AI 的 ChatMemory 抽象、会话持久化,并演示如何在不同 AI 客户端之间灵活切换。

下一篇《记忆与持久化:构建一个记得你的聊天机器人》见。


本系列博客基于 Spring AI 1.1.6 和 Spring AI Alibaba 1.1.2.0 版本编写。Spring AI Alibaba 生态更新频繁,建议在实际开发时查阅 Spring AI Alibaba 官方文档 获取最新版本信息和 API 变更。百炼平台模型列表和计费规则请参考 阿里云百炼官方文档

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐