【AI微服务】【Spring AI Alibaba】 ④ 深度实战:从零构建通义千问聊天服务(2025 最新版)

📖目录

  • [1. 引言:为什么你需要关心 Spring AI Alibaba?](#1. 引言:为什么你需要关心 Spring AI Alibaba?)
  • [2. 大白话理解:Spring AI 到底干了啥?](#2. 大白话理解:Spring AI 到底干了啥?)
  • [3. 第一步:获取 API Key 并配置](#3. 第一步:获取 API Key 并配置)
  • [4. 工程结构概览](#4. 工程结构概览)
  • [5. 源码解析一:`DashScopeChatModelController` ------ 底层直连模式](#5. 源码解析一:DashScopeChatModelController —— 底层直连模式)
    • [5.1 简单同步调用](#5.1 简单同步调用)
    • [5.2 流式响应(打字机效果)](#5.2 流式响应(打字机效果))
    • [5.3 获取 Token 使用统计](#5.3 获取 Token 使用统计)
    • [5.4 自定义推理参数(temperature, top_p 等)](#5.4 自定义推理参数(temperature, top_p 等))
  • [6. 源码解析二:`DashScopeChatClientController` ------ 高层封装模式](#6. 源码解析二:DashScopeChatClientController —— 高层封装模式)
    • [6.1 构造 ChatClient(带日志插件)](#6.1 构造 ChatClient(带日志插件))
    • [6.2 简单调用 vs 流式调用(更简洁!)](#6.2 简单调用 vs 流式调用(更简洁!))
      • [6.2.1 简单调用](#6.2.1 简单调用)
      • [6.2.2 流式调用](#6.2.2 流式调用)
    • [6.3 多模态图像分析(核心亮点!)](#6.3 多模态图像分析(核心亮点!))
      • [6.3.1 通过图片 URL 分析](#6.3.1 通过图片 URL 分析)
      • [6.3.2 通过文件上传分析](#6.3.2 通过文件上传分析)
  • [7. 架构流程图](#7. 架构流程图)
  • [8. 核心数学思想(简化但不失真)](#8. 核心数学思想(简化但不失真))
  • [9. 经典书籍推荐(2025 年仍值得读)](#9. 经典书籍推荐(2025 年仍值得读))
  • [10. 总结与下一步](#10. 总结与下一步)
  • [11. 下一步建议:](#11. 下一步建议:)
  • [12. 系列回顾:Spring AI Alibaba 技术演进三部曲](#12. 系列回顾:Spring AI Alibaba 技术演进三部曲)
    • [12.1 第一篇:《【Spring AI Alibaba】① 技术内核全解析》](#12.1 第一篇:《【Spring AI Alibaba】① 技术内核全解析》)
    • [12.2 第二篇:《【Spring AI Alibaba】② Agent 深度实战》](#12.2 第二篇:《【Spring AI Alibaba】② Agent 深度实战》)
    • [12.3 第三篇:《【Spring AI Alibaba】③ Agent 核心执行流程源码解析》](#12.3 第三篇:《【Spring AI Alibaba】③ Agent 核心执行流程源码解析》)
    • [12.4 四篇文章的关系图谱](#12.4 四篇文章的关系图谱)

1. 引言:为什么你需要关心 Spring AI Alibaba?

2024--2025 年,大模型(LLM)已从"玩具"变成"基础设施"。但直接调用 API 写胶水代码?太原始了。

Spring AI 的出现,就是为了解决这个问题------它提供了一套标准化、可插拔、面向 Spring Boot 开发者 的 LLM 集成框架。而 Spring AI Alibaba 是其对阿里云百炼平台(DashScope)的官方适配实现,让你一行代码就能接入 通义千问(Qwen)系列模型

⚠️ 注意:Spring AI 迭代极快!很多 2023--2024 年初的教程已失效。本文基于 2025 年 12 月仍可运行的最新实践,确保你复制即用。


2. 大白话理解:Spring AI 到底干了啥?

想象你要点外卖:

  • 传统方式:你打电话给餐厅,说"我要一份宫保鸡丁",对方听不清你还得重复三遍,最后送错了你也没法追责。
  • Spring AI 方式 :你打开美团 App,选好菜、填地址、付钱、实时追踪骑手------整个过程结构化、可追踪、可扩展

Spring AI 就是那个"美团 App"

  • 它把你的自然语言请求(Prompt)封装成标准对象;
  • 自动处理 HTTP 请求、Token 计算、流式响应、错误重试;
  • 返回结构化结果(文本、Token 用量、元数据等);
  • 还支持"插件"(Advisor)做日志、缓存、审计。

Spring AI Alibaba,就是专门对接"阿里系餐厅"(通义千问)的美团子频道。


3. 第一步:获取 API Key 并配置

只需两步:

  1. 前往 阿里云百炼平台 → 创建项目 → 获取 API Key
  2. 替换 application.yaml 中的占位符:
yaml 复制代码
# 【插入】application.yaml
server:
  port: 10000

spring:
  application:
    name: spring-ai-alibaba-dashscope-chat-example
  ai:
    dashscope:
      api-key: sk-你的真实密钥  # ←←← 这里替换!
      restclient:
        message-codec: json
        uri-encoding: UTF-8

logging:
  level:
    org.springframework.ai: debug
    com.alibaba.dashscope.api: debug

✅ 提示:开启 debug 日志可看到完整请求/响应,方便调试。


4. 工程结构概览

复制代码
src/
└── main/
    ├── java/
    │   └── org.example.springaialibabaexample2.demos.web/
    │       ├── DashScopeChatModelController.java   ← 底层 ChatModel 调用
    │       └── DashScopeChatClientController.java  ← 高层 ChatClient 调用
    └── resources/
        └── application.yaml

我们重点解析两个 Controller。


5. 源码解析一:DashScopeChatModelController ------ 底层直连模式

这个类演示了 最原始但最灵活 的调用方式,直接使用 ChatModel 接口。

5.1 简单同步调用

java 复制代码
// 使用默认提示词发起一次完整对话,返回最终结果
@GetMapping("/simple/chat")
public String simpleChat() {
    return dashScopeChatModel.call(
        new Prompt(
            DEFAULT_PROMPT, 
            DashScopeChatOptions.builder()
                .withModel("qwen-plus")  // ← 指定使用 qwen-plus 模型
                .build()
        )
    ).getResult().getOutput().getText();
}

💡 关键点Prompt 对象 = 用户输入 + 模型参数(如 temperature、top_p)。

这种方式适合一次性问答,比如客服机器人回答固定问题。

执行结果:


5.2 流式响应(打字机效果)

java 复制代码
// 返回 Flux<String>,实现逐字输出(类似 ChatGPT 打字效果)
@GetMapping("/stream/chat")
public Flux<String> streamChat(HttpServletResponse response) {
    response.setCharacterEncoding("UTF-8"); // 避免中文乱码
    
    // 调用 .stream() 方法,返回响应流
    Flux<ChatResponse> stream = dashScopeChatModel.stream(
        new Prompt(DEFAULT_PROMPT, DashScopeChatOptions.builder()
            .withModel("qwen-plus")
            .build())
    );
    
    // 从每个 chunk 中提取文本片段
    return stream.map(resp -> resp.getResult().getOutput().getText());
}

🌐 网络层面 :底层使用 SSE(Server-Sent Events)或 HTTP Chunked Transfer,前端可用 EventSourcefetch 流式读取。

执行结果:


5.3 获取 Token 使用统计

java 复制代码
// 返回输入/输出/总 Token 数,用于成本控制
@GetMapping("/tokens")
public Map<String, Object> tokens(HttpServletResponse response) {
    ChatResponse chatResponse = dashScopeChatModel.call(
        new Prompt(DEFAULT_PROMPT, DashScopeChatOptions.builder()
            .withModel("qwen-plus")
            .build())
    );
    
    Map<String, Object> res = new HashMap<>();
    res.put("output", chatResponse.getResult().getOutput().getText());
    res.put("input_token", chatResponse.getMetadata().getUsage().getPromptTokens());
    res.put("output_token", chatResponse.getMetadata().getUsage().getCompletionTokens());
    res.put("total_token", chatResponse.getMetadata().getUsage().getTotalTokens());
    return res;
}

💰 实用价值:企业级应用必须监控 Token 消耗!按量计费场景下,这是成本核心指标。

执行结果:


5.4 自定义推理参数(temperature, top_p 等)

java 复制代码
// 编程方式覆盖默认参数,优先级高于 application.yaml
@GetMapping("/custom/chat")
public String customChat() {
    DashScopeChatOptions customOptions = DashScopeChatOptions.builder()
        .withTopP(0.7)        // 核采样阈值:只考虑概率累计前 70% 的词
        .withTopK(50)         // 只从概率最高的 50 个词中采样
        .withTemperature(0.8) // 控制随机性:越高越"有创意",越低越"确定"
        .build();
        
    return dashScopeChatModel.call(new Prompt(DEFAULT_PROMPT, customOptions))
             .getResult().getOutput().getText();
}

🎲 大白话解释参数

  • temperature=0.1 → 像背书,答案稳定但死板
  • temperature=1.0 → 像喝醉,可能胡说八道但有惊喜
  • top_p=0.9 → "我只考虑那些加起来占 90% 概率的词"
  • top_k=50 → "我最多看前 50 个候选词"

执行结果:


6. 源码解析二:DashScopeChatClientController ------ 高层封装模式

ChatClient 是 Spring AI 推荐的现代调用方式,支持链式编程和插件机制。

6.1 构造 ChatClient(带日志插件)

java 复制代码
// 在构造时注入全局配置和插件
public DashScopeChatClientController(ChatModel chatModel) {
    this.dashScopeChatClient = ChatClient.builder(chatModel)
        .defaultAdvisors(new SimpleLoggerAdvisor()) // ← 自动打印请求/响应日志
        .defaultOptions(DashScopeChatOptions.builder()
            .withTopP(0.7)
            .build())
        .build();
}

📝 Advisor 是什么

类似 Spring AOP 的拦截器。SimpleLoggerAdvisor 会在每次调用前后自动 log 输入输出,无需手动写 System.out.println

执行结果:


6.2 简单调用 vs 流式调用(更简洁!)

6.2.1 简单调用

java 复制代码
// 同步调用:一行搞定
@GetMapping("/simple/chat")
public String simpleChat() {
    return dashScopeChatClient.prompt(DEFAULT_PROMPT).call().content();
}

执行结果

6.2.2 流式调用

java 复制代码
// 流式调用:同样一行
@GetMapping("/stream/chat")
public Flux<String> streamChat(HttpServletResponse response) {
    response.setCharacterEncoding("UTF-8");
    return dashScopeChatClient.prompt(DEFAULT_PROMPT).stream().content();
}

优势 :代码更简洁,且天然继承 defaultOptionsAdvisor

执行结果:


6.3 多模态图像分析(核心亮点!)

Spring AI Alibaba 支持 图文混合输入,调用通义千问 VL(Vision-Language)模型。

6.3.1 通过图片 URL 分析

java 复制代码
@GetMapping("/image/analyze/url")
public String analyzeImageByUrl(
    @RequestParam(defaultValue = "请分析这张图片的内容") String prompt,
    @RequestParam String imageUrl) {
    
    try {
        // 1. 构造 Media 对象(代表一张图片)
        List<Media> mediaList = List.of(
            new Media(MimeTypeUtils.IMAGE_JPEG, new URI(imageUrl))
        );
        
        // 2. 构造 UserMessage(包含文本 + 图片)
        UserMessage message = UserMessage.builder()
            .text(prompt)
            .media(mediaList)
            .build();
            
        // 3. 关键!标记消息格式为 IMAGE(否则模型当纯文本处理)
        message.getMetadata().put(
            DashScopeApiConstants.MESSAGE_FORMAT, 
            MessageFormat.IMAGE
        );
        
        // 4. 指定使用视觉模型 + 启用多模态
        Prompt chatPrompt = new Prompt(message, DashScopeChatOptions.builder()
            .withModel("qwen-vl-max-latest")     // ← 视觉最强模型
            .withMultiModel(true)                // ← 必须开启!
            .withVlHighResolutionImages(true)    // ← 支持高分辨率
            .withTemperature(0.7)
            .build());
            
        // 5. 调用
        return dashScopeChatClient.prompt(chatPrompt).call().content();
    } catch (Exception e) {
        return "图片分析失败: " + e.getMessage();
    }
}

执行结果:


6.3.2 通过文件上传分析

java 复制代码
@PostMapping("/image/analyze/upload")
public String analyzeImageByUpload(
    @RequestParam(defaultValue = "请分析这张图片的内容") String prompt,
    @RequestParam("file") MultipartFile file) {
    
    try {
        if (!file.getContentType().startsWith("image/")) {
            return "请上传图片文件";
        }
        
        // 直接从 MultipartFile 构造 Media
        Media media = new Media(
            MimeTypeUtils.parseMimeType(file.getContentType()),
            file.getResource()  // Spring Resource 抽象
        );
        
        UserMessage message = UserMessage.builder()
            .text(prompt)
            .media(media)
            .build();
            
        message.getMetadata().put(
            DashScopeApiConstants.MESSAGE_FORMAT, 
            MessageFormat.IMAGE
        );
        
        Prompt chatPrompt = new Prompt(message, DashScopeChatOptions.builder()
            .withModel("qwen-vl-max-latest")
            .withMultiModel(true)
            .withVlHighResolutionImages(true)
            .withTemperature(0.7)
            .build());
            
        return dashScopeChatClient.prompt(chatPrompt).call().content();
    } catch (Exception e) {
        return "图片分析失败: " + e.getMessage();
    }
}

请求构建

执行结果:

🖼️ 应用场景

  • 电商商品图自动描述
  • 医疗影像初步筛查
  • 教育作业拍照解题
  • 工业质检图像报告生成
    【插入】此处应放置两张截图:
  1. Postman 上传图片后返回 JSON 分析结果
  2. 浏览器访问 /image/analyze/url?imageUrl=https://xxx.jpg 的响应

7. 架构流程图

graph TD A[HTTP 请求] --> B{路径匹配} B -->|/model/*| C[DashScopeChatModelController] B -->|/client/*| D[DashScopeChatClientController] C --> E[构造 Prompt + Options] D --> F[构造 Prompt + Options + Advisor] E --> G[调用 ChatModel.call() 或 .stream()] F --> H[调用 ChatClient.prompt().call() 或 .stream()] G & H --> I[Spring AI Alibaba Adapter] I --> J[DashScope REST API (qwen-plus / qwen-vl)] J --> K[阿里云百炼平台] K --> J --> I --> L[结构化响应] L --> M[返回 JSON / Flux] style C fill:#e6f7ff,stroke:#1890ff style D fill:#f6ffed,stroke:#52c41a style I fill:#fff7e6,stroke:#fa8c16

🔁 关键抽象层ChatModel 是接口,DashScopeChatModel 是其实现;ChatClient 是更高层封装,不改变底层通信逻辑。


8. 核心数学思想(简化但不失真)

虽然我们不训练模型,但理解其生成逻辑有助于调参。

LLM 的本质是 自回归语言模型,其核心公式为:

P ( w t ∣ w 1 , w 2 , ... , w t − 1 ) = softmax ( W h t − 1 + b ) P(w_t | w_1, w_2, \dots, w_{t-1}) = \text{softmax}(W h_{t-1} + b) P(wt∣w1,w2,...,wt−1)=softmax(Wht−1+b)

其中:

  • w t w_t wt:第 t t t 个词
  • h t − 1 h_{t-1} ht−1:前 t − 1 t-1 t−1 个词的上下文向量(由 Transformer 编码)
  • W , b W, b W,b:模型参数

🥟 生活比喻

你吃饺子,咬第一口( w 1 w_1 w1)是皮,第二口( w 2 w_2 w2)尝到肉馅,第三口( w 3 w_3 w3)你预测 下一口可能是醋(因为前面是饺子)------这就是条件概率 P ( 醋 ∣ 皮 , 肉 ) P(\text{醋} | \text{皮}, \text{肉}) P(醋∣皮,肉)。

temperature 参数作用于 softmax 前的 logits:

P ( w t ) = softmax ( z T ) , z = W h t − 1 + b P(w_t) = \text{softmax}\left( \frac{z}{T} \right), \quad z = W h_{t-1} + b P(wt)=softmax(Tz),z=Wht−1+b

  • T → 0 T \to 0 T→0:分布尖锐 → 总选最高概率词(确定性)
  • T → ∞ T \to \infty T→∞:分布平坦 → 几乎随机(创造性)

9. 经典书籍推荐(2025 年仍值得读)

书名 作者 推荐理由
《Building LLM-Powered Applications》 Harrison Chase (LangChain 作者) 唯一聚焦 LLM 应用工程的书,涵盖 RAG、Agent、Tool Calling,2024 年出版,极新
《AI Engineering》 Chip Huyen 从模型到产品的全链路实践,含部署、监控、成本优化
《Deep Learning for Coders with fastai and PyTorch》 Jeremy Howard 用代码讲透 DL 原理,适合程序员入门

❌ 不推荐纯理论古籍(如 2016 年《Deep Learning》),除非你想研究反向传播推导。


10. 总结与下一步

本文带你从零跑通 Spring AI Alibaba 最新版本,涵盖:

  • 同步/流式文本对话
  • Token 统计
  • 多模态图像分析
  • 参数调优(temperature/top_p)
  • 架构分层解析

你只需

  1. 申请 API Key
  2. 替换 application.yaml
  3. 启动服务 → 调用 /model/simple/chat 即可看到通义千问回复!

可点击附件直接下载


11. 下一步建议:

  • 添加 Function Calling 实现工具调用(如查天气、查数据库)
  • 集成 RAG(检索增强生成) 提升知识准确性
  • 使用 Prometheus + Grafana 监控 Token 消耗与延迟

12. 系列回顾:Spring AI Alibaba 技术演进三部曲

在深入本文实战之前,有必要回顾本系列前作所构建的技术认知阶梯 。这三篇文章层层递进,分别聚焦于 架构设计 → 智能体(Agent)能力 → 执行流程源码,共同构成了 Spring AI Alibaba 的完整知识图谱。

本文(第四篇)则站在前三篇的肩膀上,聚焦 "开箱即用" ------提供一套可直接运行、覆盖主流场景、适配 2025 年最新版本的工程化示例,降低读者从理论到落地的门槛。


12.1 第一篇:《【Spring AI Alibaba】① 技术内核全解析》

🔗 博客文章链接

核心贡献 :首次系统拆解 Spring AI Alibaba 的三层架构插件化哲学

本文继承该思想 :所有 Controller 均注入 ChatModelChatClient 接口,而非具体实现类,确保未来可平滑迁移至 Ollama、Llama Cloud 等后端。


12.2 第二篇:《【Spring AI Alibaba】② Agent 深度实战》

🔗 博客文章链接

核心贡献 :将 LLM 从"问答机器"升级为 具备记忆、工具调用、流式响应能力的智能体(Agent)

🔗 本文与之关系

本文的 /client/stream/chat/model/stream/chat 正是 流式响应 的基础实现;而图像分析接口则隐含了 多模态工具调用 的雏形。若你想构建更复杂的 Agent(如"看图写报告"),可在此基础上集成第二篇的 Memory 与 Tool Calling 能力。


12.3 第三篇:《【Spring AI Alibaba】③ Agent 核心执行流程源码解析》

🔗 博客文章链接

核心贡献 :深入 ReactAgent 内部,揭示 Agent 如何一步步思考并行动

🔍 本文的定位

第三篇适合框架贡献者或深度定制者 阅读。而本文面向应用开发者,提供"拿来即用"的 Controller 示例。二者互补:你可先用本文快速上线功能,再根据第三篇优化内部执行逻辑。


12.4 四篇文章的关系图谱

提供架构基础 定义接口规范 展示高级能力 反哺设计理解 快速验证 依赖接口 1 技术内核 2 Agent 实战 4 本文: 开箱即用示例 3 执行流程源码

💡 阅读建议

  • 新手:从本文(④)开始 → 回看①理解设计 → 尝试②构建 Agent
  • 架构师:精读①+③,掌握扩展点
  • 业务开发者:重点参考②+④,快速交付功能

通过这四篇文章,我们完成了从 "是什么" → "怎么用" → "怎么改" → "怎么跑" 的完整闭环。希望这套系列能成为 Java 开发者拥抱大模型时代的标准参考手册

相关推荐
糖葫芦君2 小时前
Lora模型微调
人工智能·算法
编码小哥2 小时前
OpenCV几何变换详解:缩放、旋转与平移
人工智能·opencv·计算机视觉
gallonyin2 小时前
【AI智能体】Cline核心文件编辑工具分析(replace_in_file)
人工智能·架构·智能体
roamingcode2 小时前
IncSpec 面向 AI 编程助手的增量规范驱动开发工具
人工智能·agent·claude·cursor·fe·规范驱动开发
此处不留情2 小时前
从零构建智能水果识别系统:数据模块深度解析
人工智能·pytorch
YJlio2 小时前
2025 我用 Sysinternals 打通 Windows 排障“证据链”:开机慢 / 安装失败 / 磁盘暴涨(三个真实案例复盘)
人工智能·windows·笔记
Felaim2 小时前
【自动驾驶】SparseWorld-TC 论文总结(理想)
人工智能·机器学习·自动驾驶
2401_841495642 小时前
【自然语言处理】自然语言理解的 “问题识别之术”
人工智能·自然语言处理·情感分类·决策·自动问答·自然语言理解·多源信息
Coder_Boy_2 小时前
【人工智能应用技术】-基础实战-小程序应用(基于springAI+百度语音技术)智能语音开关
人工智能·百度·小程序