SpringCloudAliaba生成式JavaAI应用开发文生问答音像

news2024/9/22 5:39:38

采用SpringCloudAliabaAI型式大模型LLM,进行生成式JavaAI应用开发,实现文生问答、图像和语音合成,Web应用页面交互展现。SpringBootGradle软件框架,Idea集成开发环境,API_Post嵌入插件一体测试。

1 工效展示[文生-答/图/音]

2 软件体系架构[SpringBootGradle]

3 Idea开发环境项目导入

4 SpringAlibabaAI依赖添加

5 application.yml调度配置

6 AI服务支撑

6.1 AI答/图/音服务接口编码

6.2 AI答/图/音服务实现编码

关键的LLM运用编码如下:

@Override

public String completion(String message) {

    Prompt prompt = new Prompt(new UserMessage(message));

    return chatClient.call(prompt).getResult().getOutput().getContent();

}

@Override

public ImageResponse genImg(String imgPrompt) {

    var prompt = new ImagePrompt(imgPrompt);

    return imageClient.call(prompt);

}

@Override

public Map<String, String> streamCompletion(String message) {

    StringBuilder fullContent = new StringBuilder();

    streamingChatClient.stream(new Prompt(message))

        .flatMap(chatResponse -> Flux.fromIterable(chatResponse.getResults()))

        .map(content -> content.getOutput().getContent())

        .doOnNext(fullContent::append)

        .last()

        .map(lastContent -> Map.of(message, fullContent.toString()))

        .block();

    return Map.of(message, fullContent.toString());

}

@Override

public String genAudio(String text) {

    var resWAV = speechClient.call(text);

    return save(resWAV, SpeechSynthesisAudioFormat.WAV.getValue());

}

private String save(ByteBuffer audio, String type) { // 将语音保存到本地的方法

    String currentPath = System.getProperty("user.dir");

    LocalDateTime now = LocalDateTime.now();

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd-HH-mm-ss");

    String fileName = currentPath + File.separator + now.format(formatter) + "." + type;

    File file = new File(fileName);

    try (FileOutputStream fos = new FileOutputStream(file)) {

        fos.write(audio.array());

    } catch (Exception e) {

        throw new RuntimeException(e);

    }

    return fileName;

}

6.3 Saas服务/Web展现编码

核心的文生问答/音像部分的SaaS支撑编码如下:

private final TongYiService tongYiService;

public TongYiController(TongYiService tongYiService) {

    this.tongYiService = tongYiService;

}

@GetMapping("/chat")

public String completion(@RequestParam(value = "message",  defaultValue = "Tell me a joke") String message) {

    return tongYiService.completion(message);

}

@GetMapping("/stream")

public Map<String, String> streamCompletion(@RequestParam(

    value = "message", defaultValue = "请告诉我西红柿炖牛腩怎么做?")  String message) {

    return tongYiService.streamCompletion(message);

}

@GetMapping("/genImg")

public ImageResponse genImg(@RequestParam(value = "prompt",

    defaultValue = "Painting a picture of blue water and blue sky.")  String imgPrompt) {

    return tongYiService.genImg(imgPrompt);

}

@GetMapping("/getImgUrl")

public String getImgUrl(@RequestParam(value = "prompt",

    defaultValue = "Painting a picture of blue water and blue sky.")  String imgPrompt) {

    ImageResponse imageResponse = tongYiService.genImg(imgPrompt);

    return imageResponse.getResult().getOutput().getUrl();

}

@GetMapping("/getImgEtt")

public ResponseEntity<byte[]> getImgEtt(@RequestParam(value = "msg",

    defaultValue = "动漫女主图片") String imgPrompt){

    ImageResponse imageResponse = tongYiService.genImg(imgPrompt);

    String b64Json = imageResponse.getResult().getOutput().getB64Json();

    byte[] decode = Base64.getDecoder().decode(b64Json);

    HttpHeaders httpHeaders = new HttpHeaders();

    httpHeaders.setContentType(MediaType.IMAGE_PNG);

    return new ResponseEntity<>(decode,httpHeaders, HttpStatus.OK);

}

@GetMapping("/genAudio")

public String genAudio(@RequestParam(value = "prompt",

    defaultValue = "你好,Spring Cloud Alibaba AI 框架!") String prompt) {

    return tongYiService.genAudio(prompt);

}

@GetMapping("/speech")

public void speech(@RequestParam(value = "prompt",  defaultValue = "Tell me a joke") String prompt,

    HttpServletResponse response) throws IOException {

    String audio = tongYiService.genAudio(prompt);

    FileInputStream is = new FileInputStream(audio);

    int i = is.available();                       // 得到文件大小

    byte[] data = new byte[i];

    is.read(data);                             // 读数据

    is.close();

    response.setContentType("audio/wav");       // 设置返回的文件类型

    OutputStream toClient = response.getOutputStream();

    toClient.write(data);                       // 向客户端输出二进制数据的对象数据

    toClient.close();

}

//文字输入语音输出答案

@GetMapping("/cvtMp3")

public void cvtMp3(@RequestParam(value = "message",  defaultValue = "Tell me a joke") String message,

    HttpServletResponse response) throws IOException {

    String completion = tongYiService.completion(message);

    String audio = tongYiService.genAudio(completion);

    FileInputStream is = new FileInputStream(audio);

    int i = is.available();                      // 得到文件大小

    byte[] data = new byte[i];

    is.read(data);                            // 读数据

    is.close();

    response.setContentType("audio/wav");      // 设置返回的文件类型

    OutputStream toClient = response.getOutputStream();

    toClient.write(data);                      // 向客户端输出二进制数据的对象数据

    toClient.close();

}

7 服务功能测调试

逐一测试,核心的文生问答/音像部分的控制器SaaS支撑服务调用函数,下面列出不同方式的典型截图。

7.1 API_Post

Idea插件API_Post,针对getImg的测试截图,如下:

完全的API_Post环境,针对getImg的测试截图,如下:

7.2 浏览器端

8 Web交互应用实现

8.1 文生问答

单轮、多轮或流式文生问答展现,以多轮文生问答为例,相关编码如下:

<!DOCTYPE html>

<html lang="zh">

  <head>

    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />

    <meta name="viewport" content="user-scalable=no, initial-scale=1,

      maximum-scale=1, minimum-scale=1, width=device-width">

    <title>文生问答</title>

    <script src="js/marked.min.js"></script>

    <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 { color: #2ecc71; text-align: center; margin-bottom: 30px; }

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

       input[type="text"] { width: 100%; 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: 100% }

       .chat-box { width: 100%; height: 500px; padding: 10px;

         border: 1px solid #ccc; border-radius: 3px; overflow-y: scroll }

      .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>Spring Cloud Alibaba AI</h1>

    <form id="form">

      <label for="message">输入信息:</label>

      <input type="text" id="message" name="message" placeholder="输入信息!">

      <br><br>

      <input type="submit" value="提问">

    </form>

    <br>

    <div id="loader" class="loader" style="display: none;"></div>

    <div id="chat-box" class="chat-box"></div>

   </div>

  </body>

  <script>

    let loader = document.getElementById("loader")

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

      event.preventDefault()

      let messageInput = document.getElementById("message")

      let message = messageInput.value; messageInput.value = ""

      let chatBox = document.getElementById("chat-box")

      let userMessage = document.createElement("div")

      userMessage.className = "message user-message"

      userMessage.textContent = "用户: " + message

      chatBox.appendChild(userMessage)

      chatBox.scrollTop = chatBox.scrollHeight

      loader.style.display = "block"

      let xhr = new XMLHttpRequest()

      xhr.open("GET", "http://localhost:9320/chat?message=" + encodeURIComponent(message), true)

      xhr.onreadystatechange = function() {

        if (xhr.readyState === 4) {

          loader.style.display = "none"

          if (xhr.status === 200) {

            let response = xhr.responseText, botMessage = document.createElement("div")

            botMessage.className = "message bot-message"

            let 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) {

            let error = JSON.parse(xhr.responseText)

            let errorMessage = document.createElement("div")

            errorMessage.className = "message bot-message"

            errorMessage.textContent = "Bot: " + error.message

            chatBox.appendChild(errorMessage); chatBox.scrollTop = chatBox.scrollHeight

          } else {

            let 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>

</html>

8.2 文生图

<!DOCTYPE html>

<html lang="zh">

  <head>

    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />

    <meta name="viewport" content="user-scalable=no, initial-scale=1,

      maximum-scale=1, minimum-scale=1, width=device-width">

    <title>文生图片</title>

    <link rel="stylesheet" href="./css/element-ui.2.15.14.css">

    <script type="text/javascript" src="./js/vue.min.js"></script>

    <script type="text/javascript" src="./js/axios.min.js"></script>

    <script type="text/javascript" src="./js/element-ui.2.15.14.js"></script>

  </head>

  <body style="background: #F0FFFF;">

   <div id="app" >

    <div >

       <h1 >生成图片</h1>

       <el-form :inline="true">

         <el-form-item label="问题">

           <el-input v-model="imgtext" placeholder="请输入问题"></el-input>

         </el-form-item>

         <el-form-item>

           <el-button type="primary" @click="fetchAnswer">提问</el-button>

         </el-form-item>

       </el-form>

       <div v-if="imgresponse!==''">

         <img :src="imgresponse"  alt="生成的图片" width="300px" height="300px">

       </div>

    </div>

    </div>  

  </body>

  <script>

   new Vue({

    el: "#app", data: { imgtext: '', imgresponse: '' },

    methods: {

      fetchAnswer: function() {          //生成图片

        let vm = this;

        axios.get("http://localhost:9320/getImgUrl?prompt="+ this.imgtext).then(function(response) {

          vm.imgresponse = response.data

        }).catch(function(error) {

          console.log(error);

        })

      },

    }

   })

  </script>

</html>

8.3 文生语音合成

<!DOCTYPE html>

<html lang="zh">

  <head>

    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />

    <meta name="viewport" content="user-scalable=no, initial-scale=1,

      maximum-scale=1, minimum-scale=1, width=device-width">

    <title>文生语音</title>

    <link rel="stylesheet" href="./css/element-ui.2.15.14.css">

    <script type="text/javascript" src="./js/vue.min.js"></script>

    <script type="text/javascript" src="./js/axios.min.js"></script>

    <script type="text/javascript" src="./js/element-ui.2.15.14.js"></script>

  </head>

  <body style="background: #F0FFFF;">

   <div id="app" >

    <!--文字转语音-->

    <div >

      <h1 >文字转语音</h1>

      <el-form   :inline="true">

        <el-form-item label="问题">

          <el-input  v-model="mp3text" placeholder="请输入问题"></el-input>

        </el-form-item>

        <el-form-item>

          <el-button type="primary" @click="Mp3Answer">提问</el-button>

        </el-form-item>

      </el-form>

      <div v-if="mp3response!=''">

        <audio :src="mp3response" controls id="audio_demo" ></audio>

      </div>

      <div v-if="mp3text2response!=''">

        <audio :src="mp3text2response" controls id="audio_demo1" ></audio>

      </div>

    </div>

   </div>   

  </body>

  <script>

   new Vue({

    el: "#app", data: { mp3text:'', mp3response:'', mp3text2response:'' },

    methods: {

      Mp3Answer: function() {         //文字转语音

        let vm = this

        axios({

          url:'http://localhost:9320/speech?prompt='+this.mp3text, responseType:'blob'

        }).then(result=>{

          vm.mp3response = window.URL.createObjectURL(result.data)

        })               

        axios({                       //文字输出结果

          url:'http://localhost:9320/cvtMp3?message='+this.mp3text, responseType:'blob'

        }).then(result=>{

          vm.mp3text2response = window.URL.createObjectURL(result.data)

        })

      }

    }

   })

  </script>

</html>

9 浏览器运行交互测试

9.1 文生问答

9.2 文生图

9.3 文生语音合成

参考

快速开发生成式JavaAI应用--https://sca.aliyun.com/?spm=0.29160081.0.0.282a291fH6ibeR

SpringAI使用通义千问的具体步骤和方法--https://sca.aliyun.com/blog/faq/sca-user-question-history15328/

阿里出击SpringCloudAlibabaAI初体验,https://blog.csdn.net/m0_63171455/article/details/140976640,2024.8.7

10分钟接入AI大模型SpringCloudAlibaba,https://blog.csdn.net/qq_17153885/article/details/140835601,2024.8.1

让你快速入门SpringCloudAlibabaAI,https://blog.csdn.net/qq_34742146/article/details/140503128,2024.7.29

阿里也出手了SpringCloudAlibabaAI问世,https://blog.csdn.net/rong09_13/article/details/139723097,2024.6.26

AI框架之SpringAI与SpringCloudAlibabaAI使用讲解,https://blog.csdn.net/u012060033/article/details/139461527,2024.6.6

spring-cloud-starter-alibaba-ai无法引入如何处理--https://sca.aliyun.com/blog/faq/sca-user-question-history15816/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2120522.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

牛津大学:自动发现跨领域高阶抽象泛化框架

随着LLM等技术的快速发展&#xff0c;进一步的抽象和泛化问题亦被看作是未来AI甚至AGI发展的关键。 然而鉴于当前不论是LLM下的自回归AR条件预测Gen方法还是CV领域的diffusion扩散Gen方法&#xff0c;甚至于传统DNN的无监督学习模式&#xff0c;在所涉及的更多通用或领域场景下…

Java+Swing用户信息管理系统

JavaSwing用户信息管理系统 一、系统介绍二、功能展示1.管理员登陆2.用户信息查询3.用户信息添加4.用户信息修改5.用户信息删除 三、系统实现1.UserDao .java 四、其它1.其他系统实现 一、系统介绍 该系统实现了管理员系统登陆、用户信息查询、用户信息添加、用户信息修改、用…

大模型→世界模型下的「认知流形」本质·上

本篇内容节选自今年初我撰写的那篇10万的文章《融合RL与LLM思想&#xff0c;探寻世界模型以迈向AGI》&#xff0c;其观点也是文章中核心中的核心。 想进一步完整阅读电子版的伙伴大家可关注评论联系我&#xff0c;节选内容如下↓ “...存在一个大的开放的tokenization世界。 …

解锁SQL基础应用新境界:从入门到精通的扩展实践指南(SQL扩展)

作者简介&#xff1a;我是团团儿&#xff0c;是一名专注于云计算领域的专业创作者&#xff0c;感谢大家的关注 座右铭&#xff1a; 云端筑梦&#xff0c;数据为翼&#xff0c;探索无限可能&#xff0c;引领云计算新纪元 个人主页&#xff1a;团儿.-CSDN博客 目录 前言&#…

Unity AnimationClip详解(1)

【动画片段】 前文我们介绍了骨骼动画&#xff0c;在Unity中骨骼动画的部分静态数据存储在SkinedMeshRender中&#xff0c;而另一部分动态的关键帧数据就是存储在AnimationClip中的。 关键帧数据来自与FBX、OBJ等动画模型文件&#xff0c;可以在动画导入后的Animation选项卡中…

通信工程学习:什么是GSMP通用交换机管理协议

GSMP&#xff1a;通用交换机管理协议 GSMP&#xff08;General Switch Management Protocol&#xff0c;通用交换机管理协议&#xff09;是一种用于IP交换机对ATM交换机进行控制的协议。以下是对GSMP的详细解释&#xff1a; 一、定义与概述 GSMP是一种异步协议&#xff0c;它在…

Python画笔案例-040 绘制五角星顶圆

1、绘制五角星顶圆 通过 python 的turtle 库绘制五角星顶圆&#xff0c;如下图&#xff1a; 2、实现代码 绘制五角星顶圆&#xff0c;以下为实现代码&#xff1a; """五角星顶圆.py """ import turtledef draw_circle(d):turtle.left(90)for _ …

C#/.NET/.NET Core技术前沿周刊 | 第 4 期(2024年9.1-9.8)

前言 C#/.NET/.NET Core技术前沿周刊&#xff0c;你的每周技术指南针&#xff01;记录、追踪C#/.NET/.NET Core领域、生态的每周最新、最实用、最有价值的技术文章、社区动态、优质项目和学习资源等。让你时刻站在技术前沿&#xff0c;助力技术成长与视野拓宽。 欢迎投稿&…

客户端绑定本地端口与服务器建立连接的详细实现

客户端绑定本地端口与服务器建立连接的详细实现 一、网络编程基础1.1 TCP/IP协议1.2 套接字(Socket)1.3 客户端与服务器模型二、客户端程序的设计2.1 需求分析2.2 流程设计三、具体代码实现3.1 伪代码3.2 C代码实现四、代码详解4.1 初始化套接字库4.2 创建套接字4.3 绑定本地…

嵌入式Linux学习笔记-C语言编译过程

c语言的编译分为4个过程&#xff0c;分别是预处理&#xff0c;编译&#xff0c;汇编&#xff0c;链接。 一、预处理 预处理是c语言编译的第一个阶段&#xff0c;该任务主要由预处理器完成。预处理器会根据预处理指令对源代码进行处理&#xff0c;将预处理指令替换为相应的内容…

Learn ComputeShader 12 Setting up a buffer-based particle effect

unity有自己的粒子系统&#xff0c;但是这次我们要尝试创建一个我们自己的粒子系统&#xff0c;而且使用计算着色器有下面这些好处。总而言之&#xff0c;计算着色器适合处理大规模的数据集。例如&#xff0c;能够高效地处理数万个甚至数百万个粒子的计算。这对于粒子系统这样的…

【HarmonyOS】骨架屏(数据请求回来之前使用组件生成骨架屏,数据回来以后【骨架屏】消失)不会让页面白屏显示空

#骨架屏作用用途 骨架屏用途就是防止用户焦虑&#xff08;为了迷惑用户&#xff09; #效果图 #思路&#xff1a; #步骤&#xff1a; 1.首先是封装一个骨架 &#xff08;所使用的思路就是利用 linearGradient translate animation onAppear 实现骨架的闪光效果&#xff09…

【计算机网络】电路交换、报文交换和分组交换——三种交换方式性能分析

【计算机网络】电路交换、报文交换和分组交换——三种交换方式性能分析 目录 【计算机网络】电路交换、报文交换和分组交换——三种交换方式性能分析电路交换性能分析报文交换性能分析分组交换性能分析对比 电路交换性能分析 4Kb 需要8毫秒 数据传送需要11ms 报文交换性能分…

数组与贪心算法——452、435、646、406、169(1简4中)

452. 用最少数量的箭引爆气球&#xff08;中等&#xff09; 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points &#xff0c;其中points[i] [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。 一支弓箭可…

Python自带日志库实现springboot彩色效果

整体目标 涉及的库均为Python3自带库实现 loggingsysenum 终端显示彩色基本原理参考&#x1f449;Terminal里的颜色的那些事 Python打印日志可以直接借用logging自带的库实现&#xff0c;但是默认的打印实在太丑了&#xff0c;长下面这样 这只是一条日志看着还好比较清爽&…

VUE+Tailwind网页开发

从nodejs官网下载安装包并安装&#xff1a;https://nodejs.org/zh-cn 参考vue官网步骤配置项目&#xff1a;https://cn.vuejs.org/guide/quick-start.html $ npm create vuelatest $ cd <your-project-name> $ npm install 参考&#xff0c;安装vue-router:安装 | Vue…

【CanMV K230】矩形检测

【CanMV K230】矩形检测 什么是 矩形检测矩形检测应用领域1.目标检测2.自动驾驶3.医学图像处理4.智能零售5.图像识别6.计算机视觉 K230应用相关函数官方例程 本篇内容&#xff1a; 什么是 矩形检测矩形检测应用领域K230应用&#xff08;包含相应函数及例程&#xff09; B站视频…

【有啥问啥】HashHop在LTM-2-mini中的应用:解锁长期记忆模型的新纪元

HashHop在LTM-2-mini中的应用&#xff1a;解锁长期记忆模型的新纪元 引言 随着AI技术的飞速发展&#xff0c;模型在处理复杂任务和数据时所需的上下文窗口大小也在不断扩展。深度学习模型在处理超长上下文时&#xff0c;往往面临着计算资源消耗高、上下文丢失等问题。近期&am…

通信工程学习:什么是IFMP(Ipsilon流管理协议)

IFMP&#xff1a;Ipsilon流管理协议 IFMP&#xff08;Ipsilon Flow Management Protocol&#xff09;&#xff0c;即Ipsilon流量管理协议&#xff0c;是一种用于网络流量管理的协议。它主要用于IP交换机、IP交换网关或IP主机中&#xff0c;通过控制数据传送&#xff0c;将现有网…

【H2O2|全栈】更多关于HTML(1)HTML进阶(一)

目录 HTML进阶知识 前言 准备工作 标签的扩展&#xff08;一&#xff09; 本文中的标签在什么位置使用&#xff1f; title标签 meta标签 name viewport referrer http-equiv charset content link标签 实际案例 可视部分 代码分析 其他标签 base标签 styl…