Spring AI Alibaba + 通义千问,开发AI应用如此简单!!!

简介: 本文介绍了如何使用Spring AI Alibaba开发一个简单的AI对话应用。通过引入`spring-ai-alibaba-starter`依赖和配置API密钥,结合Spring Boot项目,只需几行代码即可实现与AI模型的交互。具体步骤包括创建Spring Boot项目、编写Controller处理对话请求以及前端页面展示对话内容。此外,文章还介绍了如何通过添加对话记忆功能,使AI能够理解上下文并进行连贯对话。最后,总结了Spring AI为Java开发者带来的便利,简化了AI应用的开发流程。

前言

没想到只会Java的我,有一天也能开发一个AI应用,怎么说呢?

Spring 官方自从发布了 Spring AI,基于 Spring AI 和通义千问大模型的 Spring AI Alibaba 也跟随其后。Alibaba 的出现也就意味着国内的 Javaer 们也能很轻松的开发AI应用了。那么本文就基于 Spring AI Alibaba 开发一个简单的 AI 对话应用。

效果展示

Spring AI 实现的AI对话

实现步骤

基于 Spring AI Alibaba 实现这样一个AI对话非常简单,只需要几行代码就可以完成。可以跟着下面的步骤操作:

创建一个 SpringBoot 项目

Spring AI Alibaba 提供了 SpringBoot starter。所以,第一步就是创建一个SpringBoot项目引入依赖以及配置。

pom.xml文件添加spring-ai-alibaba-starter依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud.ai</groupId>
        <artifactId>spring-ai-alibaba-starter</artifactId>
        <version>1.0.0-M3.1</version>
    </dependency>
</dependencies>

application.yml添加

server:
  port: 8080

spring:
  application:
    name: spring-ai-alibaba-chat
  ai:
    dashscope:
      api-key: xxxx

配置中的api-key是阿里云百炼大模型平台的凭证,AI的实现最终会调用该模型。

api-key 申请

这里有两个事项需要注意:

  1. Spring AI Alibaba 基于 Spring Boot 3.x 开发,所以JDK 版本要求为 17 及以上。
  2. spring-ai 相关依赖包还没有发布到中央仓库,本地 Maven 仓库要添加以下配置。
<repositories>
  <repository>
    <id>spring-milestones</id>
    <name>Spring Milestones</name>
    <url>https://repo.spring.io/milestone</url>
    <snapshots>
      <enabled>false</enabled>
    </snapshots>
  </repository>
</repositories>

编写与大模型交互的 Controller

项目创建成功之后,只需要写一个Controller就可以实现与AI对话,代码如下:

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

    private final ChatClient chatClient;

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


    @GetMapping("/chat")
    public String chat(String message) {
   
        return this.chatClient.prompt()
                .user(message)
                .call()
                .content();
    }
}

代码中的ChatClient类似于应用程序开发中的服务层,只不过这里由spring-ai-alibaba-starter自动初始化了实例,可以直接提供 AI 服务,最终会调用百炼大模型。

此时就可以启动应用,通过浏览器访问localhost:8080/ai/chat?message= 进行对话。

编写通过页面进行对话的 html

为了直观的展示效果,简单实现一个前端和接口交互,通过页面进行AI对话。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <script src="js/marked.min.js"></script>
    <title></title>
    <style>
        body {
    
            background-color: #f8f9fa;
            font-family: Arial, sans-serif;
        }

        .container {
    
            margin: 50px auto;
            width: 800px;
            background-color: #fff;
            padding: 20px;
            border-radius: 5px;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
        }

        h1 {
    
            text-align: center;
            margin-bottom: 30px;
        }

        label {
    
            display: block;
            margin-bottom: 10px;
            color: #333;
        }

        input[type="text"] {
    
            width: 85%;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 3px;
        }

        input[type="submit"] {
    
            background-color: #2ecc71;
            color: #fff;
            border: none;
            padding: 10px 20px;
            border-radius: 3px;
            cursor: pointer;
            width: 10%;
        }

        .chat-box {
    
            width: 100%;
            height: 500px;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 3px;
            overflow-y: scroll;
        }

        .message {
    
            margin-bottom: 10px;
            padding: 10px;
            background-color: #f1f1f1;
            border-radius: 3px;
        }

        .user-message {
    
            background-color: #2ecc71;
            color: #fff;
        }

        .bot-message {
    
            background-color: #e6aa6b;
            color: #fff;
        }

        .loader {
    
            text-align: center;
        }

        .loader::after {
    
            content: "";
            display: inline-block;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            border: 2px solid #ccc;
            border-top-color: #2ecc71;
            animation: spin 1s infinite linear;
        }

        @keyframes spin {
    
            to {
    
                transform: rotate(360deg);
            }
        }
    </style>
</head>
<body>
<div class="container">
    <h1>AI 对话</h1>
    <form id="form" style="width: 47%;position: absolute;bottom: 150px;margin-left:15px">
        <input type="text" id="message" name="message" placeholder="输入你的问题">
        <input type="submit" value="发送">
    </form>
    <br>
    <div id="loader" class="loader" style="display: none;"></div>
    <div id="chat-box" class="chat-box"></div>
</div>

<script>
    var loader = document.getElementById("loader");

    document.getElementById("form").addEventListener("submit", function(event) {
    
        event.preventDefault();

        var messageInput = document.getElementById("message");
        var message = messageInput.value;
        messageInput.value = "";

        var chatBox = document.getElementById("chat-box");

        var userMessage = document.createElement("div");
        userMessage.className = "message";
        userMessage.textContent = "我: " + message;
        chatBox.appendChild(userMessage);
        chatBox.scrollTop = chatBox.scrollHeight;

        loader.style.display = "block";

        var xhr = new XMLHttpRequest();
        xhr.open("GET", "http://localhost:8080/ai/chat?message=" + encodeURIComponent(message), true);
        xhr.onreadystatechange = function() {
    
            if (xhr.readyState === 4) {
    
                loader.style.display = "none";

                if (xhr.status === 200) {
    
                    var response = xhr.responseText;

                    var botMessage = document.createElement("div");
                    botMessage.className = "message bot-message";

                    var botMessageText = document.createElement("span");
                    botMessageText.className = "message-text";
                    botMessage.appendChild(botMessageText);
                    botMessageText.innerHTML = marked.marked(response);

                    chatBox.appendChild(botMessage);
                    chatBox.scrollTop = chatBox.scrollHeight;
                } else if (xhr.status === 400) {
    
                    var error = JSON.parse(xhr.responseText);

                    var errorMessage = document.createElement("div");
                    errorMessage.className = "message bot-message";
                    errorMessage.textContent = "Bot: " + error.message;
                    chatBox.appendChild(errorMessage);
                    chatBox.scrollTop = chatBox.scrollHeight;
                } else {
    
                    var errorMessage = document.createElement("div");
                    errorMessage.className = "message bot-message";
                    errorMessage.textContent = "Bot: Failed to connect to the backend service. Please make sure the backend service is running.";
                    chatBox.appendChild(errorMessage);
                    chatBox.scrollTop = chatBox.scrollHeight;
                }
            }
        };

        xhr.onloadstart = function() {
    
            loader.style.display = "block";
        };

        xhr.onloadend = function() {
    
            loader.style.display = "none";
        };

        xhr.send();
    });
</script>
</body>
</html>

js 引入的 marked.min.js 可以去GitHub或者联系我获取。

至此,就实现了文中开头的AI对话效果。

需要了解的基本知识

上面的示例其实就是一个SpringBoot项目,对于Javaer肯定不陌生。而对于没有人工智能相关背景的人来说,如果想要基于 Spring AI 开发一个AI应用产品,还是需要了解一些基本概念的。

  • AI 模型:AI 模型是旨在处理和生成信息的算法,通常模仿人类的认知功能。我们现在基本上听到的大模型都属于生成式AI模型,例如通义千问。
  • Prompt:提示词作为生成式大模型的输入,可以指导模型生成特定的输出。如果搭建过智能体就会知道,创建一个智能体首先要设置一些提示词。
  • Token:token作为 AI 模型工作原理的基石,输入时,模型将单词转换为token,输出时,将token转换回单词。在现在的AI模型背景下,token就相当于金钱,一次调用的费用就越高。
  • 模型的认知:一个模型的诞生需要在海量的训练集中进行学习,所以它的认知中没有未来的知识。如果想让模型对现有知识产生认知,有微调、检索增强生成 (RAG)、函数调用这几种方式。

对于本文示例中来说,每一次的对话就是模型的一次token输入和输出。

实现有记忆的对话

如果运行了上面的示例,并且进行了几轮对话,会发现大模型并不会理解上下文,也无法实现连贯的对话。

就如上面所说的“模型的认知”,大模型不会记录对话,所以不会产生上下文关联。例如我接下来的问答中,并没有按照我的提问生成“冒险的”故事,只是“冒险的”进行了说明。

Spring AI 实现的AI对话

那如何让大模型能够追踪、理解并利用先前对话上下文的能力?

spring-ai 支持基于chat memory的对话记忆。在上面的代码中,只需要在构建chatClient时添加两行代码。

private ChatMemory chatMemory = new InMemoryChatMemory();                                            

public AIChatController(ChatClient.Builder builder) {
                                                   
    this.chatClient = builder                                                                        
            .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory, UUID.randomUUID().toString(), 10))
            .build();                                                                                
}

UUID 会作为此次对话的唯一标识,ChatMemory会将之前的对话内容记录下来,每次对模型的输入就是历史的对话记录,最终实现对话记忆。

这种做法最终会影响使用大模型的成本,就如上面所说,输入和输出都会影响总token数量,而token就相当于金钱。

最后看一下对话记忆效果

总结

Spring AI解决了AI集成的核心难题:即无缝连接企业数据、API与AI模型,同时也简化了Java 开发人员对AI应用的编程复杂度,还提供检索增强生成 (RAG)、函数调用等关键功能。对于Java 开发人员来讲,通过 Spring AI 可以探索更多的 AI 应用场景。

相关文章
|
8天前
|
XML JSON Java
Spring Boot 开发中常见的错误
本文总结了 Java 开发中常见的几个问题及其改进方法,包括:1. 过度使用 `@Component` 注解;2. `@ResponseBody` 注解的错误用法;3. `@Autowired` 的不当使用;4. `application.properties` 管理不善;5. 异常处理不当。每部分详细解释了错误情况和建议的改进方案,并提供了相应的代码示例。
39 11
|
9天前
|
人工智能 小程序 API
【一步步开发AI运动小程序】十七、如何识别用户上传视频中的人体、运动、动作、姿态?
【云智AI运动识别小程序插件】提供人体、运动、姿态检测的AI能力,支持本地原生识别,无需后台服务,具有速度快、体验好、易集成等优点。本文介绍如何使用该插件实现用户上传视频的运动识别,包括视频解码抽帧和人体识别的实现方法。
|
9天前
|
IDE Java 测试技术
互联网应用主流框架整合之Spring Boot开发
通过本文的介绍,我们详细探讨了Spring Boot开发的核心概念和实践方法,包括项目结构、数据访问层、服务层、控制层、配置管理、单元测试以及部署与运行。Spring Boot通过简化配置和强大的生态系统,使得互联网应用的开发更加高效和可靠。希望本文能够帮助开发者快速掌握Spring Boot,并在实际项目中灵活应用。
26 5
|
7天前
|
前端开发 Java 开发者
这款免费 IDEA 插件让你开发 Spring 程序更简单
Feign-Helper 是一款支持 Spring 框架的 IDEA 免费插件,提供 URL 快速搜索、Spring Web Controller 路径一键复制及 Feign 与 Controller 接口互相导航等功能,极大提升了开发效率。
|
3月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
2月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
241 2
|
1天前
|
Java 数据库连接 Maven
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
自动装配是现在面试中常考的一道面试题。本文基于最新的 SpringBoot 3.3.3 版本的源码来分析自动装配的原理,并在文未说明了SpringBoot2和SpringBoot3的自动装配源码中区别,以及面试回答的拿分核心话术。
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
|
8天前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
52 14
|
1月前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
49 1
SpringBoot入门(7)- 配置热部署devtools工具
|
1月前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
47 2
 SpringBoot入门(7)- 配置热部署devtools工具