SpringAI整合AI大模型(1)

1.SpringAI简介

引言
随着人工智能(AI)技术的快速发展,越来越多的传统软件开发框架开始尝试与 AI 技术结合,以提升开发效率、优化系统性能并提供更智能的功能。作为 Java 生态中最流行的开发框架之一,Spring Framework 在企业级应用开发中占据重要地位。而 SpringAI 是一个假设性但极具前瞻性的概念,它代表了 Spring 框架与人工智能技术深度融合的可能性。本文将探讨 SpringAI 的潜在定义、应用场景以及未来发展方向。

什么是 SpringAI?
SpringAI 并不是一个当前存在的具体项目或工具,而是对 Spring Framework 在未来可能集成人工智能技术的一种设想。可以将其理解为一种扩展或增强版的 Spring Framework,旨在通过引入 AI 技术,使开发者能够更高效地构建智能化应用程序。

核心理念
自动化与智能化:利用机器学习和深度学习算法,自动完成代码生成、测试用例创建、性能调优等任务。
动态适应性:通过实时分析运行时数据,调整应用程序的行为以适应不同的负载条件或用户需求。
增强开发者体验:通过自然语言处理(NLP)技术,让开发者可以通过语音或文本指令与开发工具交互。

2.Spring AI 使用 (采用springAi alibaba,因为原生的springAi 对国内大模型并不友好)

2.1 pom.xml

添加Maven存储库: 在项目的pom.xml中添加spring-ai-alibaba-starter。

        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter</artifactId>
            <version>1.0.0-M5.1</version>
        </dependency>

2.2 应用场景

生成式AI:
借助 Spring AI 的生成式AI能力,开发者可以通过简明的API调用,实现高质量的文本生成、多语言翻译、智能摘要提取等功能。这些功能基于先进的自然语言处理(NLP)技术,能够显著提升应用的内容生成能力和用户体验。

矢量数据库
在需要对大规模文本数据进行语义搜索和相似性匹配时,Spring AI 提供了高效的矢量数据库支持。通过集成最新的向量检索技术,开发者可以轻松实现高精度的语义搜索功能,大幅提升数据查询的效率与相关性。

AI绘画:
针对将文本描述转化为视觉内容的需求,Spring AI 提供了强大的AI绘画功能。该功能基于生成对抗网络(GAN)和其他前沿图像生成技术,能够无缝集成到各类应用场景中,如创意设计、虚拟场景构建等,为用户提供从文本到图像的智能化转换能力。

通过以上核心功能,Spring AI 不仅简化了AI技术的应用开发流程,还为企业和开发者提供了高效、灵活的智能化解决方案。

3.Spring Cloud Alibaba AI 实践

3.1 版本选择

注意:因为 Spring AI Alibaba 基于 Spring Boot 3.x 开发,因此本地 JDK 版本要求为 17 及以上。
我选择了 JDK 17 作为运行环境,Spring Boot 3.4.3 框架。

3.2 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 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.4.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.an</groupId>
    <artifactId>aiApiClient</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>aiApiClient</name>
    <description>aiApiClient</description>

    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter</artifactId>
            <version>1.0.0-M5.1</version>
        </dependency>

        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-s3</artifactId>
            <version>1.12.261</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-core</artifactId>
            <version>5.8.31</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-crypto</artifactId>
            <version>5.8.31</version>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>32.1.3-jre</version>
        </dependency>


        <!--mybatis-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>3.5.5</version>
        </dependency>
        <!-- druid 连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-3-starter</artifactId>
            <version>1.2.20</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>3.0.4</version>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter-test</artifactId>
        <version>3.0.4</version>
        <scope>test</scope>
    </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.34</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
<!--            <plugin>-->
<!--                <groupId>org.apache.maven.plugins</groupId>-->
<!--                <artifactId>maven-compiler-plugin</artifactId>-->
<!--                <configuration>-->
<!--                    <annotationProcessorPaths>-->
<!--                        <path>-->
<!--                            <groupId>org.projectlombok</groupId>-->
<!--                            <artifactId>lombok</artifactId>-->
<!--                        </path>-->
<!--                    </annotationProcessorPaths>-->
<!--                </configuration>-->
<!--            </plugin>-->
            <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>

3.2 配置文件

此处很多配置属于自定义配置如果只想实现简单的聊天功能,配置一下端口号就好

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: ${MYSQL_USER:root}
      password: ${MYSQL_PWD:root}
      url: jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${MYSQL_DB:ai}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false
  ai:
    nacos:
      prompt:
        template:
          enabled: false
  application:
    name: aiApiClient
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
server:
  port: 8080
ai:
  chat:
    scene: 我想咨询你一些医学上的问题,你需要初步判断我的症状,以及给出开药建议以及生活方式建议,以及推荐一些医生治疗
    topP: 0.8
    model: qwen-vl-max-latest
    enableSearch: true
    multiModel: true

file:
  bucketName: ai # 默认存储桶名称
  local: # 本地文件配置信息
    enable: true # 是否开启
    basePath: D:/local/files # 默认路径
    domain: http://localhost:${server.port}

logging:
  level:
    com: DEBUG


阿里云申请api-key:获取api-key
在这里插入图片描述
说明
仅主账号拥有查看全部API-KEY的权限。主账号可以获取所有子账号的API Key,子账号仅能获取自己的API Key。
请不要将API Key以任何方式公开,避免因未经授权的使用造成安全风险或资金损失。
API Key是您的重要资产,请务必妥善保管。如果您单击操作列的删除将已有API Key删除,您将无法继续通过该Key访问百炼大模型提供的各项服务,如果您之前在某些应用程序或服务中集成了这个API Key,那么这些应用将会因为认证失败而无法正常工作。

在这里插入图片描述

3.3 设置 AI_DASHSCOPE_API_KEY 环境变量

AI_DASHSCOPE_API_KEY=阿里云上获取的apiKey
在这里插入图片描述

3.4 对接文本模型

@RestController
@RequestMapping("/api/v1")
public class AlController {


    private final ChatClient dashScopeChatClient;

    
    public AlController(ChatClient dashScopeChatClient) {
        this.dashScopeChatClient = dashScopeChatClient;
    }

    /**
     * 纯文本聊天接口
     * @param query 文本
     * @return ai回复内容
     */
    @GetMapping("/simple/chat")
    public String simpleChat(String query) {
        return dashScopeChatClient.prompt(query).call().content();
    }
 }

3.5 文本加图片输入

@RestController
@RequestMapping("/api/v1")
public class AlController {


    private final ChatClient dashScopeChatClient;


    public AlController(ChatClient dashScopeChatClient) {
        this.dashScopeChatClient = dashScopeChatClient;
    }

    /**
     * 纯文本聊天接口
     * @param query 文本
     * @return ai回复内容
     */
    @GetMapping("/simple/chat")
    public String simpleChat(String query) {
        return dashScopeChatClient.prompt(query).call().content();
    }

    /**
     * 图片+文本接口
     * @param prompt 文本
     * @param imageFile 文件
     * @param response 响应体
     * @return ai回复内容
     */
    @PostMapping("/imageRecognition")
    public String imageRecognition(
            @RequestParam(value = "prompt") String prompt,
            @RequestPart(value = "image",required = false) MultipartFile imageFile,
            HttpServletResponse response) throws IOException {

        if (Objects.isNull(imageFile)) {
            return dashScopeChatClient
                    .prompt(prompt)
                    .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, DEFAULT_CHAT_MEMORY_CONVERSATION_ID)
                            .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                    .call().content();
        }
        UserMessage message = buildAlMsg(prompt, imageFile, response);

        return dashScopeChatClient.prompt(
                new Prompt(message)
        ).advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, DEFAULT_CHAT_MEMORY_CONVERSATION_ID)
                .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10)).call().content();
    }


    /**
     * 图片+文本接口
     * @param prompt 文本
     * @param url 图片资源url
     * @return ai回复内容
     */
    @PostMapping("/recognition")
    public String recognition(
            @RequestParam(value = "prompt") String prompt,
            @RequestParam(value = "url",required = false) String url) throws IOException {

        if (StrUtil.isBlank(url)) {
            return dashScopeChatClient
                    .prompt(prompt)
                    .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, DEFAULT_CHAT_MEMORY_CONVERSATION_ID)
                            .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                    .call().content();
        }

        Resource resource = convertUrlToResource(url);

        // 创建 MimeType 对象
        MimeType mimeType = MimeTypeUtils.parseMimeType(Objects.requireNonNull(APPLICATION_OCTET_STREAM));

        List<Media> mediaList = List.of(new Media(mimeType, resource));
        UserMessage message = new UserMessage(prompt, mediaList);
        message.getMetadata().put(DashScopeChatModel.MESSAGE_FORMAT, MessageFormat.IMAGE);

        return dashScopeChatClient.prompt(
                new Prompt(message)
        ).advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, DEFAULT_CHAT_MEMORY_CONVERSATION_ID)
                .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10)).call().content();

    }

    public static Resource convertUrlToResource(String urlString) throws MalformedURLException {
        URL url = new URL(urlString);

        return new UrlResource(url);
    }

完整代码地址

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐