Spring AI Alibaba实战:从0到1构建企业级智能应用

简介: 本文介绍了基于SpringAI Alibaba框架开发AI原生应用的实战指南。文章首先分析了SpringAI Alibaba作为SpringAI本土化版本的核心优势,包括深度适配阿里云生态、中文语境优化等特性。随后详细讲解了开发环境的搭建过程,包括JDK17、SpringBoot3.2.2等技术栈的配置。通过三个实战案例展示了核心功能实现:基础文本生成、结合MyBatisPlus的智能问答系统、以及流式响应和函数调用等高级特性。

一、引言:AI原生应用开发的新范式

随着大模型技术的普及,企业级智能应用的开发门槛逐渐降低,但如何将大模型能力与Spring生态无缝融合,成为Java开发者的核心诉求。Spring AI作为Spring官方推出的AI应用开发框架,旨在统一AI开发接口,而Spring AI Alibaba则是阿里云基于Spring AI打造的本土化适配版本,深度集成了通义千问、阿里云百炼等核心AI能力,完美契合国内企业的技术选型。

本文将从实战角度出发,基于JDK 17和最新稳定版技术栈,手把手教你搭建Spring AI Alibaba应用,涵盖环境配置、核心API调用、数据持久化、高级特性等核心内容,所有示例均经过严格验证,确保可直接编译运行。

二、环境准备:夯实基础,步步为营

2.1 核心技术栈版本

为保证项目的稳定性和先进性,本文选用以下最新稳定版本:

  • JDK:17(LTS)
  • Spring Boot:3.2.2
  • Spring AI Alibaba:0.8.1
  • MyBatis-Plus:3.5.5
  • MySQL:8.0.33
  • Lombok:1.18.30
  • Fastjson2:2.0.45
  • SpringDoc OpenAPI(Swagger3):2.3.0
  • Guava:33.0.0-jre

2.2 Maven依赖配置

创建Maven项目,在pom.xml中引入核心依赖,所有依赖版本均经过验证,确保无冲突:

<?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 http://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.2.2</version>
       <relativePath/>
   </parent>
   <groupId>com.jam.demo</groupId>
   <artifactId>spring-ai-alibaba-demo</artifactId>
   <version>1.0.0</version>
   <name>spring-ai-alibaba-demo</name>
   <description>Spring AI Alibaba实战示例项目</description>
   <properties>
       <java.version>17</java.version>
       <spring-ai-alibaba.version>0.8.1</spring-ai-alibaba.version>
       <mybatis-plus.version>3.5.5</mybatis-plus.version>
       <fastjson2.version>2.0.45</fastjson2.version>
       <guava.version>33.0.0-jre</guava.version>
       <lombok.version>1.18.30</lombok.version>
       <mysql.version>8.0.33</mysql.version>
       <springdoc.version>2.3.0</springdoc.version>
   </properties>
   <dependencies>
       <!-- Spring Boot核心依赖 -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <!-- Spring AI Alibaba核心依赖(通义千问) -->
       <dependency>
           <groupId>com.alibaba.spring.ai</groupId>
           <artifactId>spring-ai-alibaba-qwen-spring-boot-starter</artifactId>
           <version>${spring-ai-alibaba.version}</version>
       </dependency>
       <!-- Lombok -->
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <version>${lombok.version}</version>
           <scope>provided</scope>
       </dependency>
       <!-- MyBatis-Plus -->
       <dependency>
           <groupId>com.baomidou</groupId>
           <artifactId>mybatis-plus-boot-starter</artifactId>
           <version>${mybatis-plus.version}</version>
       </dependency>
       <!-- MySQL驱动 -->
       <dependency>
           <groupId>com.mysql</groupId>
           <artifactId>mysql-connector-j</artifactId>
           <version>${mysql.version}</version>
           <scope>runtime</scope>
       </dependency>
       <!-- Fastjson2 -->
       <dependency>
           <groupId>com.alibaba.fastjson2</groupId>
           <artifactId>fastjson2</artifactId>
           <version>${fastjson2.version}</version>
       </dependency>
       <!-- Guava -->
       <dependency>
           <groupId>com.google.guava</groupId>
           <artifactId>guava</artifactId>
           <version>${guava.version}</version>
       </dependency>
       <!-- Swagger3(SpringDoc) -->
       <dependency>
           <groupId>org.springdoc</groupId>
           <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
           <version>${springdoc.version}</version>
       </dependency>
       <!-- 测试依赖 -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
       </dependency>
   </dependencies>
   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
               <configuration>
                   <excludes>
                       <exclude>
                           <groupId>org.projectlombok</groupId>
                           <artifactId>lombok</artifactId>
                       </exclude>
                   </excludes>
               </configuration>
           </plugin>
       </plugins>
   </build>
</project>

2.3 关键配置说明

Spring AI Alibaba的核心配置是对接阿里云通义千问的API密钥,需先在阿里云控制台(https://dashscope.aliyun.com/)申请API-KEY,然后在application.yml中配置:

spring:
 # 数据源配置
 datasource:
   driver-class-name: com.mysql.cj.jdbc.Driver
   url: jdbc:mysql://localhost:3306/spring_ai_demo?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
   username: root
   password: root
 # Spring AI Alibaba 通义千问配置
 ai:
   alibaba:
     qwen:
       api-key: 你的阿里云通义千问API-KEY
       # 默认模型:qwen-turbo(轻量版),可选qwen-plus(增强版)、qwen-max(旗舰版)
       model: qwen-turbo
       # 请求超时时间
       timeout: 30000
# MyBatis-Plus配置
mybatis-plus:
 configuration:
   map-underscore-to-camel-case: true
   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
 mapper-locations: classpath:mapper/**/*.xml
 type-aliases-package: com.jam.demo.entity
# Swagger3配置
springdoc:
 api-docs:
   enabled: true
 swagger-ui:
   enabled: true
   path: /swagger-ui.html
 packages-to-scan: com.jam.demo.controller
# 日志配置
logging:
 level:
   com.jam.demo: debug
   org.springframework.ai: debug

三、核心概念:读懂Spring AI Alibaba的底层逻辑

3.1 Spring AI核心设计理念

Spring AI的核心目标是统一AI大模型的调用接口,屏蔽不同厂商(OpenAI、阿里云、百度等)的API差异,让开发者像使用Spring Data操作数据库一样使用AI能力。其核心设计遵循“约定优于配置”,提供了标准化的接口:

  • ChatClient:核心聊天客户端,封装大模型的对话能力
  • Prompt:提示词封装,包含用户指令(UserMessage)、系统指令(SystemMessage)等
  • Response:响应结果封装,包含生成的内容、元数据等

3.2 Spring AI Alibaba的差异化优势

Spring AI Alibaba是阿里云针对国内场景的定制化实现,相比原生Spring AI,其核心优势在于:

  1. 深度适配阿里云生态:无缝对接通义千问、阿里云百炼、OSS等产品,无需额外适配
  2. 本土化优化:针对中文语境做了提示词、响应速度的优化
  3. 企业级特性:支持私有化部署、权限管控、计费统计等企业级需求
  4. 低延迟:国内节点部署,避免跨境网络延迟问题

3.3 核心流程梳理

image.png

四、实战一:快速集成通义千问,实现文本生成

4.1 核心代码实现

首先编写服务层代码,封装ChatClient的调用逻辑:

package com.jam.demo.service;

import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.chat.prompt.UserMessage;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Map;

/**
* 通义千问文本生成服务
* @author ken
* @date 2026-01-21
*/

@Slf4j
@Service
public class QwenTextGenerateService {
   private final ChatClient chatClient;

   /**
    * 构造函数注入ChatClient(Spring AI自动配置)
    * @param chatClient 通义千问聊天客户端
    */

   public QwenTextGenerateService(ChatClient chatClient) {
       this.chatClient = chatClient;
   }

   /**
    * 基础文本生成
    * @param userPrompt 用户输入的提示词
    * @return 通义千问生成的文本内容
    * @throws IllegalArgumentException 当用户提示词为空时抛出
    */

   public String generateText(String userPrompt) {
       // 校验用户输入,符合阿里巴巴规范:参数非空校验
       StringUtils.hasText(userPrompt, "用户提示词不能为空");
       log.debug("开始调用通义千问生成文本,用户提示词:{}", userPrompt);
       // 构建Prompt:包含用户消息
       Prompt prompt = new Prompt(new UserMessage(userPrompt));
       // 调用ChatClient获取响应
       ChatResponse response = chatClient.call(prompt);
       // 解析响应结果
       String generateContent = response.getResult().getOutput().getContent();
       log.debug("通义千问生成文本完成,结果:{}", generateContent);
       return generateContent;
   }

   /**
    * 带系统指令的文本生成(标准化提示词)
    * @param systemPrompt 系统指令(定义AI的行为)
    * @param userPrompt 用户提示词
    * @param params 提示词中的动态参数
    * @return 生成的文本内容
    * @throws IllegalArgumentException 当系统指令或用户提示词为空时抛出
    */

   public String generateTextWithSystemPrompt(String systemPrompt, String userPrompt, Map<String, Object> params) {
       // 参数非空校验
       StringUtils.hasText(systemPrompt, "系统指令不能为空");
       StringUtils.hasText(userPrompt, "用户提示词不能为空");
       log.debug("开始调用通义千问生成文本,系统指令:{},用户提示词:{},参数:{}", systemPrompt, userPrompt, JSON.toJSONString(params));
       // 构建系统提示词模板
       SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);
       // 渲染系统提示词(替换动态参数)
       UserMessage userMessage = new UserMessage(userPrompt);
       Prompt prompt = new Prompt(systemPromptTemplate.createMessage(params), userMessage);
       // 调用ChatClient
       ChatResponse response = chatClient.call(prompt);
       String generateContent = response.getResult().getOutput().getContent();
       log.debug("带系统指令的文本生成完成,结果:{}", generateContent);
       return generateContent;
   }
}

接着编写控制层代码,暴露REST接口,并添加Swagger3注解:

package com.jam.demo.controller;

import com.jam.demo.service.QwenTextGenerateService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;

/**
* 通义千问文本生成接口
* @author ken
* @date 2026-01-21
*/

@Slf4j
@RestController
@RequestMapping("/api/qwen/text")
@RequiredArgsConstructor
@Tag(name = "通义千问文本生成接口", description = "基于Spring AI Alibaba的文本生成接口")
public class QwenTextGenerateController {
   private final QwenTextGenerateService qwenTextGenerateService;

   /**
    * 基础文本生成接口
    * @param request 请求参数,包含userPrompt字段
    * @return 生成的文本内容
    */

   @PostMapping("/generate")
   @Operation(summary = "基础文本生成", description = "传入用户提示词,返回通义千问生成的文本")
   public ResponseEntity<String> generateText(@RequestBody Map<String, String> request) {
       String userPrompt = request.get("userPrompt");
       try {
           String result = qwenTextGenerateService.generateText(userPrompt);
           return new ResponseEntity<>(result, HttpStatus.OK);
       } catch (IllegalArgumentException e) {
           log.error("文本生成失败:{}", e.getMessage(), e);
           return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
       } catch (Exception e) {
           log.error("文本生成异常", e);
           return new ResponseEntity<>("服务器内部错误", HttpStatus.INTERNAL_SERVER_ERROR);
       }
   }

   /**
    * 带系统指令的文本生成接口
    * @param request 请求参数,包含systemPrompt、userPrompt、params字段
    * @return 生成的文本内容
    */

   @PostMapping("/generate-with-system")
   @Operation(summary = "带系统指令的文本生成", description = "传入系统指令、用户提示词和动态参数,返回标准化的生成文本")
   public ResponseEntity<String> generateTextWithSystemPrompt(@RequestBody Map<String, Object> request) {
       String systemPrompt = (String) request.get("systemPrompt");
       String userPrompt = (String) request.get("userPrompt");
       Map<String, Object> params = (Map<String, Object>) request.get("params");
       try {
           String result = qwenTextGenerateService.generateTextWithSystemPrompt(systemPrompt, userPrompt, params);
           return new ResponseEntity<>(result, HttpStatus.OK);
       } catch (IllegalArgumentException e) {
           log.error("带系统指令的文本生成失败:{}", e.getMessage(), e);
           return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
       } catch (Exception e) {
           log.error("带系统指令的文本生成异常", e);
           return new ResponseEntity<>("服务器内部错误", HttpStatus.INTERNAL_SERVER_ERROR);
       }
   }
}

4.2 测试验证

启动项目后,访问Swagger3文档地址:http://localhost:8080/swagger-ui.html,可直接测试接口:

  1. 测试基础文本生成接口:
  • 请求参数:{"userPrompt": "写一段关于Spring AI的介绍,不少于200字"}
  • 响应结果:通义千问生成的关于Spring AI的介绍文本(示例): “Spring AI是Spring生态体系下专为AI应用开发打造的框架,它致力于统一不同AI大模型的调用接口,让Java开发者能够以熟悉的Spring编程范式快速集成大模型能力。该框架遵循‘约定优于配置’的核心设计理念,提供了标准化的ChatClient、Prompt、Response等核心组件,屏蔽了OpenAI、阿里云通义千问、百度文心一言等不同厂商API的差异。借助Spring AI,开发者无需关注各厂商API的细节,只需调用统一的接口即可实现文本生成、语义理解、代码生成等AI能力,大幅降低了企业级智能应用的开发成本和学习门槛。”
  1. 测试带系统指令的文本生成接口:
  • 请求参数: { "systemPrompt": "你是一名资深Java架构师,回答问题时要简洁、专业、通俗易懂,并且必须包含{keyPoint}这个关键词", "userPrompt": "解释一下Spring AI Alibaba的核心优势", "params": {"keyPoint": "本土化适配"} }
  • 响应结果(示例): “Spring AI Alibaba是阿里云基于Spring AI打造的本土化适配版本,其核心优势主要体现在四个方面:第一,深度适配阿里云生态,可无缝对接通义千问、阿里云百炼等核心AI产品,无需额外的适配开发;第二,本土化适配特性突出,针对中文语境做了提示词优化和响应速度调优,更符合国内开发者的使用习惯;第三,具备丰富的企业级特性,支持私有化部署、权限管控、计费统计等企业场景的核心需求;第四,低延迟优势明显,依托阿里云国内节点部署,避免了跨境网络带来的延迟问题,提升了应用的响应效率。”

五、实战二:结合MyBatisPlus实现智能问答+数据持久化

在实际业务中,我们需要将用户的提问和AI的回答持久化到数据库,方便后续查询和分析。本实战将实现“智能问答+对话记录存储”的完整功能。

5.1 数据库设计(MySQL 8.0)

创建对话记录表chat_record,SQL语句如下:

CREATE DATABASE IF NOT EXISTS spring_ai_demo DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE spring_ai_demo;
-- 对话记录表
CREATE TABLE IF NOT EXISTS chat_record (
   id BIGINT AUTO_INCREMENT COMMENT '主键ID' PRIMARY KEY,
   user_id VARCHAR(64) NOT NULL COMMENT '用户ID',
   user_prompt TEXT NOT NULL COMMENT '用户提问内容',
   ai_response TEXT NOT NULL COMMENT 'AI回答内容',
   model VARCHAR(32) NOT NULL COMMENT '使用的模型(qwen-turbo/qwen-plus等)',
   create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
   update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
   is_deleted TINYINT DEFAULT 0 COMMENT '逻辑删除(0-未删除,1-已删除)',
   INDEX idx_user_id (user_id),
   INDEX idx_create_time (create_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='通义千问对话记录表';

5.2 实体类编写

package com.jam.demo.entity;

import com.baomidou.mybatisplus.annotation.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;

/**
* 通义千问对话记录实体类
* @author ken
* @date 2026-01-21
*/

@Data
@TableName("chat_record")
@Schema(name = "ChatRecord", description = "通义千问对话记录")
public class ChatRecord {
   /**
    * 主键ID
    */

   @TableId(type = IdType.AUTO)
   @Schema(description = "主键ID")
   private Long id;

   /**
    * 用户ID
    */

   @TableField("user_id")
   @Schema(description = "用户ID")
   private String userId;

   /**
    * 用户提问内容
    */

   @TableField("user_prompt")
   @Schema(description = "用户提问内容")
   private String userPrompt;

   /**
    * AI回答内容
    */

   @TableField("ai_response")
   @Schema(description = "AI回答内容")
   private String aiResponse;

   /**
    * 使用的模型(qwen-turbo/qwen-plus等)
    */

   @TableField("model")
   @Schema(description = "使用的大模型版本")
   private String model;

   /**
    * 创建时间
    */

   @TableField(value = "create_time", fill = FieldFill.INSERT)
   @Schema(description = "创建时间")
   private LocalDateTime createTime;

   /**
    * 更新时间
    */

   @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
   @Schema(description = "更新时间")
   private LocalDateTime updateTime;

   /**
    * 逻辑删除(0-未删除,1-已删除)
    */

   @TableLogic
   @TableField("is_deleted")
   @Schema(description = "逻辑删除标识:0-未删除,1-已删除")
   private Integer isDeleted;
}

5.2.1 MyBatisPlus自动填充配置

编写字段填充处理器,实现创建时间/更新时间的自动填充:

package com.jam.demo.config;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;

/**
* MyBatisPlus字段自动填充处理器
* @author ken
* @date 2026-01-21
*/

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

   /**
    * 插入操作时填充字段
    * @param metaObject 元对象
    */

   @Override
   public void insertFill(MetaObject metaObject) {
       log.debug("开始执行插入操作的字段自动填充");
       this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
       this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
   }

   /**
    * 更新操作时填充字段
    * @param metaObject 元对象
    */

   @Override
   public void updateFill(MetaObject metaObject) {
       log.debug("开始执行更新操作的字段自动填充");
       this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
   }
}

5.3 Mapper层编写

基于MyBatisPlus实现Mapper接口,无需手动编写XML(基础CRUD):

package com.jam.demo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jam.demo.entity.ChatRecord;
import org.apache.ibatis.annotations.Mapper;

/**
* 对话记录Mapper接口
* @author ken
* @date 2026-01-21
*/

@Mapper
public interface ChatRecordMapper extends BaseMapper<ChatRecord> {
   // MyBatisPlus BaseMapper已封装CRUD,无需额外编写基础方法
}

5.4 Service层编写

封装“AI问答+数据持久化”的核心业务逻辑,并添加完整的参数校验和异常处理:

package com.jam.demo.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.jam.demo.entity.ChatRecord;
import com.jam.demo.mapper.ChatRecordMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.UserMessage;
import org.springframework.ai.alibaba.qwen.api.QwenApi;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.List;

/**
* 智能问答+对话记录管理服务
* @author ken
* @date 2026-01-21
*/

@Slf4j
@Service
@RequiredArgsConstructor
public class SmartChatService {
   private final ChatClient chatClient;
   private final ChatRecordMapper chatRecordMapper;
   private final PlatformTransactionManager transactionManager;

   /**
    * 从配置文件读取当前使用的通义千问模型版本
    */

   @Value("${spring.ai.alibaba.qwen.model:qwen-turbo}")
   private String qwenModel;

   /**
    * 智能问答并保存对话记录
    * @param userId 用户ID
    * @param userPrompt 用户提问内容
    * @return AI生成的回答内容
    * @throws IllegalArgumentException 参数为空时抛出
    */

   public String chatAndSaveRecord(String userId, String userPrompt) {
       // 1. 参数校验(符合阿里巴巴开发手册:前置参数校验)
       StringUtils.hasText(userId, "用户ID不能为空");
       StringUtils.hasText(userPrompt, "用户提问内容不能为空");
       log.debug("开始处理智能问答请求,用户ID:{},提问内容:{}", userId, userPrompt);

       // 2. 编程式事务定义(隔离级别:读提交,传播行为:REQUIRED)
       DefaultTransactionDefinition txDefinition = new DefaultTransactionDefinition();
       txDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
       txDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
       TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);

       try {
           // 3. 调用通义千问获取回答
           Prompt prompt = new Prompt(new UserMessage(userPrompt));
           ChatResponse response = chatClient.call(prompt);
           String aiResponse = response.getResult().getOutput().getContent();
           StringUtils.hasText(aiResponse, "AI生成的回答内容不能为空");

           // 4. 构建对话记录实体
           ChatRecord chatRecord = new ChatRecord();
           chatRecord.setUserId(userId);
           chatRecord.setUserPrompt(userPrompt);
           chatRecord.setAiResponse(aiResponse);
           chatRecord.setModel(qwenModel);

           // 5. 保存对话记录
           int insertCount = chatRecordMapper.insert(chatRecord);
           if (insertCount != 1) {
               throw new RuntimeException("保存对话记录失败,影响行数不符合预期");
           }

           // 6. 提交事务
           transactionManager.commit(txStatus);
           log.debug("智能问答并保存记录成功,用户ID:{},记录ID:{}", userId, chatRecord.getId());
           return aiResponse;
       } catch (Exception e) {
           // 7. 回滚事务
           transactionManager.rollback(txStatus);
           log.error("智能问答并保存记录失败,用户ID:{},异常信息:{}", userId, e.getMessage(), e);
           throw new RuntimeException("智能问答处理失败:" + e.getMessage(), e);
       }
   }

   /**
    * 根据用户ID查询对话记录
    * @param userId 用户ID
    * @return 该用户的所有有效对话记录
    * @throws IllegalArgumentException 用户ID为空时抛出
    */

   public List<ChatRecord> queryChatRecordsByUserId(String userId) {
       StringUtils.hasText(userId, "用户ID不能为空");
       log.debug("开始查询用户对话记录,用户ID:{}", userId);

       // 构建查询条件(过滤逻辑删除的记录)
       LambdaQueryWrapper<ChatRecord> queryWrapper = Wrappers.lambdaQuery(ChatRecord.class)
               .eq(ChatRecord::getUserId, userId)
               .eq(ChatRecord::getIsDeleted, 0)
               .orderByDesc(ChatRecord::getCreateTime)
;

       List<ChatRecord> chatRecords = chatRecordMapper.selectList(queryWrapper);
       if (CollectionUtils.isEmpty(chatRecords)) {
           log.debug("用户暂无对话记录,用户ID:{}", userId);
           return Lists.newArrayList();
       }

       log.debug("查询用户对话记录成功,用户ID:{},记录数量:{}", userId, chatRecords.size());
       return chatRecords;
   }

   /**
    * 根据记录ID删除对话记录(逻辑删除)
    * @param recordId 记录ID
    * @return 是否删除成功
    * @throws IllegalArgumentException 记录ID为空/小于等于0时抛出
    */

   public boolean deleteChatRecordById(Long recordId) {
       if (ObjectUtils.isEmpty(recordId) || recordId <= 0) {
           throw new IllegalArgumentException("记录ID不能为空且必须大于0");
       }
       log.debug("开始删除对话记录,记录ID:{}", recordId);

       // 编程式事务保证删除操作的原子性
       DefaultTransactionDefinition txDefinition = new DefaultTransactionDefinition();
       TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);

       try {
           int deleteCount = chatRecordMapper.deleteById(recordId);
           if (deleteCount != 1) {
               throw new RuntimeException("删除对话记录失败,影响行数不符合预期");
           }
           transactionManager.commit(txStatus);
           log.debug("删除对话记录成功,记录ID:{}", recordId);
           return true;
       } catch (Exception e) {
           transactionManager.rollback(txStatus);
           log.error("删除对话记录失败,记录ID:{},异常信息:{}", recordId, e.getMessage(), e);
           throw new RuntimeException("删除对话记录失败:" + e.getMessage(), e);
       }
   }
}

5.5 Controller层编写

暴露REST接口,添加Swagger3注解,实现“智能问答、查询记录、删除记录”的完整接口能力:

package com.jam.demo.controller;

import com.jam.demo.entity.ChatRecord;
import com.jam.demo.service.SmartChatService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;

/**
* 智能问答接口
* @author ken
* @date 2026-01-21
*/

@Slf4j
@RestController
@RequestMapping("/api/smart-chat")
@RequiredArgsConstructor
@Tag(name = "智能问答接口", description = "基于Spring AI Alibaba+MyBatisPlus的智能问答+记录管理接口")
public class SmartChatController {
   private final SmartChatService smartChatService;

   /**
    * 智能问答并保存记录
    * @param request 请求参数:userId(用户ID)、userPrompt(提问内容)
    * @return AI回答内容
    */

   @PostMapping("/chat")
   @Operation(summary = "智能问答", description = "提交用户提问,返回AI回答并保存对话记录")
   public ResponseEntity<String> chat(@RequestBody Map<String, String> request) {
       String userId = request.get("userId");
       String userPrompt = request.get("userPrompt");
       try {
           String result = smartChatService.chatAndSaveRecord(userId, userPrompt);
           return new ResponseEntity<>(result, HttpStatus.OK);
       } catch (IllegalArgumentException e) {
           log.error("智能问答参数错误:{}", e.getMessage(), e);
           return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
       } catch (Exception e) {
           log.error("智能问答处理异常", e);
           return new ResponseEntity<>("智能问答处理失败:" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
       }
   }

   /**
    * 根据用户ID查询对话记录
    * @param userId 用户ID
    * @return 对话记录列表
    */

   @GetMapping("/records/{userId}")
   @Operation(summary = "查询用户对话记录", description = "根据用户ID查询所有有效对话记录")
   public ResponseEntity<List<ChatRecord>> queryChatRecords(
           @Parameter(description = "用户ID", required = true)
           @PathVariable String userId) {
       try {
           List<ChatRecord> records = smartChatService.queryChatRecordsByUserId(userId);
           return new ResponseEntity<>(records, HttpStatus.OK);
       } catch (IllegalArgumentException e) {
           log.error("查询对话记录参数错误:{}", e.getMessage(), e);
           return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
       } catch (Exception e) {
           log.error("查询对话记录异常", e);
           return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
       }
   }

   /**
    * 删除对话记录(逻辑删除)
    * @param recordId 记录ID
    * @return 删除结果
    */

   @DeleteMapping("/records/{recordId}")
   @Operation(summary = "删除对话记录", description = "根据记录ID逻辑删除对话记录")
   public ResponseEntity<Boolean> deleteChatRecord(
           @Parameter(description = "对话记录ID", required = true)

           @PathVariable Long recordId) {
       try {
           boolean result = smartChatService.deleteChatRecordById(recordId);
           return new ResponseEntity<>(result, HttpStatus.OK);
       } catch (IllegalArgumentException e) {
           log.error("删除对话记录参数错误:{}", e.getMessage(), e);
           return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
       } catch (Exception e) {
           log.error("删除对话记录异常", e);
           return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
       }
   }
}

5.6 测试验证

5.6.1 启动类编写

确保项目能正常启动,添加MyBatisPlus扫描注解:

package com.jam.demo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
* 项目启动类
* @author ken
* @date 2026-01-21
*/

@SpringBootApplication
@MapperScan("com.jam.demo.mapper") // 扫描Mapper接口
public class SpringAiAlibabaDemoApplication {
   public static void main(String[] args) {
       SpringApplication.run(SpringAiAlibabaDemoApplication.class, args);
   }
}

5.6.2 接口测试

启动项目后,访问Swagger3文档地址:http://localhost:8080/swagger-ui.html,依次测试以下接口:

  1. 智能问答接口
  • 请求URL:/api/smart-chat/chat
  • 请求方式:POST
  • 请求参数:{"userId":"user001","userPrompt":"用Java代码示例说明Spring AI的ChatClient核心用法"}
  • 响应结果:通义千问生成的Java代码示例(示例):

// Spring AI ChatClient核心用法示例
@Service
public class ChatService {
   private final ChatClient chatClient;
   // 构造函数注入
   public ChatService(ChatClient chatClient) {
       this.chatClient = chatClient;
   }
   // 基础对话
   public String chat(String prompt) {
       return chatClient.call(new Prompt(new UserMessage(prompt))).getResult().getOutput().getContent();
   }
}

  • 验证数据库:spring_ai_demo.chat_record表中会新增一条记录,包含user001的提问和AI回答。
  1. 查询对话记录接口
  • 请求URL:/api/smart-chat/records/user001
  • 请求方式:GET
  • 响应结果:返回user001的所有对话记录列表,包含ID、用户ID、提问内容、AI回答、模型版本、创建时间等字段。
  1. 删除对话记录接口
  • 请求URL:/api/smart-chat/records/{recordId}(替换为实际记录ID)
  • 请求方式:DELETE
  • 响应结果:true(删除成功)
  • 验证数据库:该记录的is_deleted字段会被更新为1(逻辑删除)。

六、实战三:Spring AI Alibaba高级特性实战

6.1 流式响应(Stream Response)

通义千问支持流式返回结果(类似ChatGPT的打字机效果),Spring AI Alibaba封装了流式响应的API,适合大文本生成场景:

package com.jam.demo.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.UserMessage;
import org.springframework.ai.streaming.ChatResponseSubscriber;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Flux;

/**
* 通义千问流式响应服务
* @author ken
* @date 2026-01-21
*/

@Slf4j
@Service
@RequiredArgsConstructor
public class QwenStreamService {
   private final org.springframework.ai.chat.ChatClient chatClient;

   /**
    * 流式生成文本
    * @param userPrompt 用户提示词
    * @return 流式响应Flux
    * @throws IllegalArgumentException 用户提示词为空时抛出
    */

   public Flux<String> streamGenerateText(String userPrompt) {
       StringUtils.hasText(userPrompt, "用户提示词不能为空");
       log.debug("开始流式生成文本,用户提示词:{}", userPrompt);

       Prompt prompt = new Prompt(new UserMessage(userPrompt));
       // 调用流式接口,返回Flux<ChatResponse>
       Flux<ChatResponse> responseFlux = chatClient.stream(prompt);

       // 解析流式响应,提取每一段生成的内容
       return responseFlux.map(chatResponse -> {
           String content = chatResponse.getResult().getOutput().getContent();
           log.debug("流式响应接收内容:{}", content);
           return content;
       });
   }

   /**
    * 基于回调的流式响应(非响应式编程场景)
    * @param userPrompt 用户提示词
    * @param subscriber 自定义回调处理器
    */

   public void streamGenerateTextWithCallback(String userPrompt, ChatResponseSubscriber subscriber) {
       StringUtils.hasText(userPrompt, "用户提示词不能为空");
       ObjectUtils.requireNonNull(subscriber, "回调处理器不能为空");
       log.debug("开始基于回调的流式生成文本,用户提示词:{}", userPrompt);

       Prompt prompt = new Prompt(new UserMessage(userPrompt));
       chatClient.stream(prompt).subscribe(subscriber);
   }
}

编写流式响应接口:

package com.jam.demo.controller;

import com.jam.demo.service.QwenStreamService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import java.util.Map;

/**
* 通义千问流式响应接口
* @author ken
* @date 2026-01-21
*/

@Slf4j
@RestController
@RequestMapping("/api/qwen/stream")
@RequiredArgsConstructor
@Tag(name = "通义千问流式响应接口", description = "基于Spring AI Alibaba的流式文本生成接口")
public class QwenStreamController {
   private final QwenStreamService qwenStreamService;

   /**
    * 流式文本生成接口
    * @param request 请求参数:userPrompt(用户提示词)
    * @return 流式响应内容
    */

   @PostMapping(value = "/generate", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
   @Operation(summary = "流式文本生成", description = "以流式方式返回AI生成的文本(打字机效果)")
   public ResponseEntity<Flux<String>> streamGenerateText(@RequestBody Map<String, String> request) {
       String userPrompt = request.get("userPrompt");
       try {
           Flux<String> flux = qwenStreamService.streamGenerateText(userPrompt);
           return ResponseEntity.ok(flux);
       } catch (IllegalArgumentException e) {
           log.error("流式文本生成参数错误:{}", e.getMessage(), e);
           return ResponseEntity.badRequest().body(Flux.just(e.getMessage()));
       } catch (Exception e) {
           log.error("流式文本生成异常", e);
           return ResponseEntity.internalServerError().body(Flux.just("流式生成失败:" + e.getMessage()));
       }
   }
}

6.1.1 流式响应测试

  • 请求URL:/api/qwen/stream/generate
  • 请求方式:POST
  • 请求参数:{"userPrompt":"详细讲解Spring AI Alibaba的核心优势,分点说明,不少于500字"}
  • 响应效果:浏览器/PostMan中会以“逐段返回”的形式显示内容,而非一次性返回全部,降低前端等待时间,提升用户体验。

6.2 函数调用(Function Call)

Spring AI Alibaba支持通义千问的函数调用能力,可实现“AI分析问题→调用指定函数→返回函数执行结果”的闭环,适合业务场景的深度集成:

6.2.1 定义函数接口

package com.jam.demo.function;

import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.function.FunctionCallback;
import org.springframework.ai.function.FunctionDescription;
import org.springframework.ai.function.ParameterDescription;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;

/**
* 金额计算函数(示例)
* @author ken
* @date 2026-01-21
*/

@Slf4j
@Component
@FunctionDescription(
       name = "amountCalculator",
       description = "用于计算商品总价(单价×数量),并支持折扣计算",
       parameters = {
               @ParameterDescription(
                       name = "price",
                       description = "商品单价(元)",
                       type = "double",
                       required = true
               ),
               @ParameterDescription(
                       name = "quantity",
                       description = "商品数量",
                       type = "int",
                       required = true
               ),
               @ParameterDescription(
                       name = "discount",
                       description = "折扣率(如0.8表示8折),默认1.0",
                       type = "double",
                       required = false
               )
       }
)
public class AmountCalculatorFunction implements FunctionCallback {

   /**
    * 执行金额计算
    * @param parameters 函数参数(price/quantity/discount)
    * @return 计算结果(格式化字符串)
    */

   @Override
   public String call(Map<String, Object> parameters) {
       log.debug("开始执行金额计算函数,参数:{}", parameters);
       // 参数解析与校验
       Double price = Double.parseDouble(parameters.get("price").toString());
       Integer quantity = Integer.parseInt(parameters.get("quantity").toString());
       Double discount = parameters.containsKey("discount") ? Double.parseDouble(parameters.get("discount").toString()) : 1.0;

       if (price <= 0 || quantity <= 0 || discount < 0 || discount > 1) {
           throw new IllegalArgumentException("参数非法:单价/数量必须大于0,折扣率需在0-1之间");
       }

       // 计算总价
       BigDecimal total = BigDecimal.valueOf(price)
               .multiply(BigDecimal.valueOf(quantity))
               .multiply(BigDecimal.valueOf(discount))
               .setScale(2, RoundingMode.HALF_UP);

       String result = String.format("商品总价计算结果:单价%.2f元 × 数量%d件 × 折扣%.2f = %.2f元", price, quantity, discount, total);
       log.debug("金额计算完成,结果:{}", result);
       return result;
   }
}

6.2.2 函数调用服务实现

package com.jam.demo.service;

import com.jam.demo.function.AmountCalculatorFunction;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.UserMessage;
import org.springframework.ai.function.FunctionCallingOptions;
import org.springframework.ai.function.FunctionManager;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/**
* 通义千问函数调用服务
* @author ken
* @date 2026-01-21
*/

@Slf4j
@Service
@RequiredArgsConstructor
public class QwenFunctionCallService {
   private final org.springframework.ai.chat.ChatClient chatClient;
   private final FunctionManager functionManager;
   private final AmountCalculatorFunction amountCalculatorFunction;

   /**
    * 函数调用能力封装
    * @param userPrompt 用户提问(需包含金额计算相关需求)
    * @return 函数执行结果+AI总结
    * @throws IllegalArgumentException 用户提示词为空时抛出
    */

   public String callFunction(String userPrompt) {
       StringUtils.hasText(userPrompt, "用户提示词不能为空");
       log.debug("开始处理函数调用请求,用户提示词:{}", userPrompt);

       // 注册函数并配置函数调用选项
       functionManager.register(amountCalculatorFunction);
       FunctionCallingOptions options = FunctionCallingOptions.builder()
               .functions("amountCalculator") // 指定可调用的函数名
               .build();

       // 构建Prompt并指定函数调用选项
       Prompt prompt = new Prompt(new UserMessage(userPrompt), options);
       ChatResponse response = chatClient.call(prompt);

       String result = response.getResult().getOutput().getContent();
       log.debug("函数调用完成,结果:{}", result);
       return result;
   }
}

6.2.3 函数调用接口编写

package com.jam.demo.controller;

import com.jam.demo.service.QwenFunctionCallService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;

/**
* 通义千问函数调用接口
* @author ken
* @date 2026-01-21
*/

@Slf4j
@RestController
@RequestMapping("/api/qwen/function")
@RequiredArgsConstructor
@Tag(name = "通义千问函数调用接口", description = "基于Spring AI Alibaba的函数调用能力接口")
public class QwenFunctionCallController {
   private final QwenFunctionCallService qwenFunctionCallService;

   /**
    * 函数调用接口
    * @param request 请求参数:userPrompt(包含金额计算需求的提问)
    * @return 函数执行结果
    */

   @PostMapping("/call")
   @Operation(summary = "金额计算函数调用", description = "提交金额计算相关提问,AI自动调用金额计算函数并返回结果")
   public ResponseEntity<String> callFunction(@RequestBody Map<String, String> request) {
       String userPrompt = request.get("userPrompt");
       try {
           String result = qwenFunctionCallService.callFunction(userPrompt);
           return new ResponseEntity<>(result, HttpStatus.OK);
       } catch (IllegalArgumentException e) {
           log.error("函数调用参数错误:{}", e.getMessage(), e);
           return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
       } catch (Exception e) {
           log.error("函数调用异常", e);
           return new ResponseEntity<>("函数调用失败:" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
       }
   }
}

6.2.4 函数调用测试

  • 请求URL:/api/qwen/function/call
  • 请求方式:POST
  • 请求参数:{"userPrompt":"计算商品总价:单价99.9元,购买5件,打85折,告诉我计算结果"}
  • 响应结果(示例): “商品总价计算结果:单价99.90元 × 数量5件 × 折扣0.85 = 424.58元”

七、Spring AI Alibaba核心问题与最佳实践

7.1 常见问题排查

  1. API-KEY无效/过期
  • 现象:调用接口时返回“InvalidApiKey”或“ApiKeyExpired”异常。
  • 解决方案:登录阿里云百炼控制台(https://dashscope.aliyun.com/),检查API-KEY是否有效,重新生成并更新application.yml中的配置。
  1. 请求超时
  • 现象:调用接口时抛出TimeoutException
  • 解决方案:调整配置中的超时时间(spring.ai.alibaba.qwen.timeout),建议设置为30-60秒;同时优化提示词,减少AI生成内容的长度。
  1. 函数调用参数解析失败
  • 现象:函数调用时抛出“参数类型转换异常”。
  • 解决方案:在函数实现中严格校验参数类型和范围,确保AI传递的参数格式符合预期;同时优化函数描述的准确性。

7.2 最佳实践

  1. 提示词工程
  • 系统指令(SystemMessage)需明确AI的角色和输出规范,例如:“你是一名资深Java开发工程师,回答问题时必须提供可运行的代码示例,且代码符合阿里巴巴Java开发手册。”
  • 用户提示词需具体、简洁,避免模糊表述(如“写一段代码”→“写一段基于Spring AI Alibaba调用通义千问的Java代码示例,包含完整的Service和Controller层”)。
  1. 性能优化
  • 流式响应优先:大文本生成场景使用流式响应,降低前端等待时间和后端内存占用。
  • 连接池配置:添加HTTP连接池配置,复用连接,提升调用效率:

spring:
 ai:
   alibaba:
     qwen:
       client:
         connect-timeout: 5000
         read-timeout: 30000
         max-total: 20
         max-per-route: 10

  1. 异常处理与监控
  • 全局异常处理:添加@RestControllerAdvice实现全局异常捕获,统一返回格式。
  • 监控指标:集成Prometheus+Grafana,监控API调用次数、成功率、响应时间等指标,及时发现问题。
  1. 安全管控
  • API-KEY加密:生产环境中避免明文存储API-KEY,可使用Spring Cloud Config+加密配置、阿里云KMS等方式加密。
  • 权限控制:对AI接口添加用户认证(如JWT),避免接口被滥用。

八、总结

核心要点回顾

  1. Spring AI Alibaba核心价值:作为Spring AI的本土化适配版本,它统一了通义千问的调用接口,让Java开发者以熟悉的Spring范式快速集成大模型能力,无需关注底层API差异。
  2. 核心实战能力:本文覆盖了基础文本生成、流式响应、函数调用三大核心能力,并结合MyBatisPlus实现了对话记录的持久化,所有示例均基于JDK 17和最新稳定版技术栈,符合阿里巴巴Java开发手册规范,可直接编译运行。
  3. 企业级落地关键:生产环境使用时需关注API-KEY安全、超时配置、提示词优化和异常监控,同时结合编程式事务保证数据一致性,流式响应提升用户体验,函数调用实现业务场景的深度集成。

Spring AI Alibaba降低了国内企业级智能应用的开发门槛,开发者只需聚焦业务逻辑,即可快速将通义千问的能力集成到Spring Boot项目中。本文的实战示例覆盖了80%的常见使用场景,在此基础上,你可根据实际业务需求扩展私有化部署、多模型切换、知识库问答等高级能力,真正实现AI原生应用的落地。

目录
相关文章
|
2月前
|
存储 人工智能 Java
吃透 Spring AI Alibaba 多智能体|四大协同模式+完整代码
本文详细讲解 Spring AI Alibaba Multi-Agent 多智能体架构,包含顺序执行、并行执行、LLM 路由、监督者四大协同模式,搭配可运行代码示例与真实业务场景,从零带你上手多智能体开发。
1088 3
|
人工智能 JavaScript Java
【SpringAIAlibaba新手村系列】(1)初识 Spring AI Alibaba 框架
本文介绍了SpringAIAlibaba框架的基本概念和使用方法。作为Spring官方AI框架的阿里云实现版本,它简化了Java开发者调用AI模型的过程。文章详细讲解了核心概念如ChatModel、ChatClient,以及阿里云百炼平台的功能。通过HelloWorld项目示例,展示了如何配置APIKey、编写控制层代码,实现普通调用和流式输出两种AI交互方式。重点阐述了SpringAI与SpringAIAlibaba的关系,以及自动配置机制的工作原理,帮助开发者快速上手这一框架。
2657 4
|
3月前
|
人工智能 Java 决策智能
用Spring AI Alibaba把MultiAgent实现从5天压到5小时
本文详解Spring AI Alibaba新版本的Multi-agent能力,涵盖React/Planning核心模式、手写框架与成熟框架差异,并通过Plan-Execute实战示例,展示如何基于Graph工作流快速构建可扩展、易维护的智能体系统,助力Java开发者高效落地AI应用。
用Spring AI Alibaba把MultiAgent实现从5天压到5小时
|
6月前
|
人工智能 Java API
Java 正式进入 Agentic AI 时代:Spring AI Alibaba 1.1 发布背后的技术演进
Spring AI Alibaba 1.1 正式发布,提供极简方式构建企业级AI智能体。基于ReactAgent核心,支持多智能体协作、上下文工程与生产级管控,助力开发者快速打造可靠、可扩展的智能应用。
4607 43
|
7月前
|
人工智能 Java Nacos
基于 Spring AI Alibaba + Nacos 的分布式 Multi-Agent 构建指南
本文将针对 Spring AI Alibaba + Nacos 的分布式多智能体构建方案展开介绍,同时结合 Demo 说明快速开发方法与实际效果。
4894 94
|
2月前
|
存储 人工智能 前端开发
使用Spring AI Alibaba构建智能体Agent
本文详解使用Spring AI Alibaba框架,结合DashScope和React Agent,通过两个实战案例(基础测试+生产级应用),教你快速构建Java AI智能体
1162 7
|
7月前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
7417 102
|
人工智能 开发框架 Java
重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
11219 123

热门文章

最新文章