Spring AI是一个面向AI工程的应用框架。其目标是将可移植性和模块化设计等设计原则应用于AI领域的Spring生态系统, 转换为人话来说就是:Spring出了一个AI框架,帮助我们快速调用AI,从而实现各种功能场景。
但是重点:对于国内开发者不太友好已经不太支持了。于是乎Spring Cloud Alibaba AI
出世了!
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/ruoyi-vue-pro 视频教程:https://doc.iocoder.cn/video/ Spring Cloud Alibaba AI
基于 Spring AI 0.8.1
版本完成通义系列大模型的接入。DashScope灵积模型服务建立在 模型即服务(Model-as-a-Service
,MaaS)的理念基础之上,围绕AI各领域模型,通过标准化的API提供包括模型推理、模型微调训练在内的多种模型服务。
目前支持的模型主要有:对话、文生图、文生语音
,更多功能特性正在适配中。那以上介绍完之后咱们就完成一些案例来看看效果吧
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/yudao-cloud 视频教程:https://doc.iocoder.cn/video/ 这里说下我本地的环境,阿里要求JDK为17+
JDK17,Maven3.5以上,Spring Boot2.0+,Spring Cloud2021+
创建项目就是正常的Maven项目
<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.0modelVersion > <groupId > com.tongyigroupId > <artifactId > tongyi2artifactId > <packaging > pompackaging > <version > 1.0-SNAPSHOTversion > <modules > <module > aliaimodule > modules > <properties > <project.build.sourceEncoding > UTF-8project.build.sourceEncoding > <java.version > 17java.version > <spring-boot.version > 2.7.18spring-boot.version > <spring-cloud.version > 2021.0.8spring-cloud.version > <spring-cloud-alibaba.version > 2021.0.5.0spring-cloud-alibaba.version > properties > <dependencyManagement > <dependencies > <dependency > <groupId > org.springframework.cloudgroupId > <artifactId > spring-cloud-dependenciesartifactId > <version > ${spring-cloud.version}version > <type > pomtype > <scope > importscope > dependency > <dependency > <groupId > com.alibaba.cloudgroupId > <artifactId > spring-cloud-alibaba-dependenciesartifactId > <version > ${spring-cloud-alibaba.version}version > <type > pomtype > <scope > importscope > dependency > <dependency > <groupId > org.springframework.bootgroupId > <artifactId > spring-boot-dependenciesartifactId > <version > ${spring-boot.version}version > <type > pomtype > <scope > importscope > dependency > dependencies > dependencyManagement >project >
创建子工程就是正常的maven项目(选中父工程右键)
<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" > <parent > <artifactId > tongyi2artifactId > <groupId > com.tongyigroupId > <version > 1.0-SNAPSHOTversion > parent > <modelVersion > 4.0.0modelVersion > <artifactId > aliaiartifactId > <properties > <project.build.sourceEncoding > UTF-8project.build.sourceEncoding > properties > <dependencies > <dependency > <groupId > org.springframework.bootgroupId > <artifactId > spring-boot-starter-webartifactId > dependency > <dependency > <groupId > com.alibaba.cloudgroupId > <artifactId > spring-cloud-starter-alibaba-aiartifactId > <version > 2023.0.1.0version > dependency > <dependency > <groupId > com.alibabagroupId > <artifactId > fastjsonartifactId > <version > 1.2.83version > dependency > dependencies > <repositories > <repository > <id > spring-milestonesid > <name > Spring Milestonesname > <url > https://repo.spring.io/milestoneurl > <snapshots > <enabled > falseenabled > snapshots > repository > repositories > <build > <plugins > <plugin > <groupId > org.apache.maven.pluginsgroupId > <artifactId > maven-compiler-pluginartifactId > <version > 3.8.1version > <configuration > <source > 17source > <target > 17target > <encoding > UTF-8encoding > configuration > plugin > <plugin > <groupId > org.springframework.bootgroupId > <artifactId > spring-boot-maven-pluginartifactId > <version > 2.7.18version > <configuration > <mainClass > com.usian.AliApplicationmainClass > <skip > trueskip > configuration > <executions > <execution > <id > repackageid > execution > executions > plugin > plugins > build >project >
主要配置阿里云申请的api-key:
https://dashscope.console.aliyun.com/model spring: cloud: ai: tongyi: api-key: your api-key #自己在阿里云官网申请的api-key server: port: 8081
以下所有案例均在一个项目中编写,小伙伴们不要整懵了哈
public interface TongYiService { //聊天对话 String completion (String message) ; }
public abstract class AbstractTongYiServiceImpl implements TongYiService { private static final String INFO_PREFIX = "please implement " ; private static final String INFO_SUFFIX = "() method." ; @Override public String completion (String message) { throw new RuntimeException(INFO_PREFIX + Thread.currentThread().getStackTrace()[2 ].getMethodName()); } }
@Service public class TongYiServiceImpl implements TongYiService { private static final String INFO_PREFIX = "please implement " ; private static final String INFO_SUFFIX = "() method." ; @Override public String completion (String message) { throw new RuntimeException(INFO_PREFIX + Thread.currentThread().getStackTrace()[2 ].getMethodName()); } }
@RestController @RequestMapping ("/ai" )@CrossOrigin public class TongYiController {/** * 聊天对话应用 单轮对话 * @param message * @return */ @GetMapping ("/example" ) public String completion (@RequestParam(value = "message" , defaultValue = "Tell me a joke" ) String message,HttpServletRequest request,HttpServletResponse response) { String completion = tongYiSimpleService.completion(message); return completion; } }
可以在地址栏输入地址进行访问http://localhost:8081/ai/example?message=讲一个笑话
以上就是Spring Cloud Alibaba AI
入门案例
可以整合Vue输入
<div id ="app" > <template > <div > <h1 > 单轮输出h1 > <el-form :inline ="true" > <el-form-item label ="问题" > <el-input v-model ="singletext" placeholder ="请输入问题" > el-input > el-form-item > <el-form-item > <el-button type ="primary" @click ="SingleAnswer" > 提问el-button > el-form-item > el-form > {{singleresponse}} div >template >div > <script > new Vue({ el : "#app" , data : { singletext :'' ,//单轮输入值 singleresponse :'' ,//单轮输出结果 }, methods : { //单轮对话 SingleAnswer : function ( ) { var vm = this ; axios.get("http://localhost:8081/ai/example?message=" +this .singletext).then(function (response ) { vm.singleresponse = response.data; }).catch(function (error ) { console .log(error); }); } } });script >
/** * 多轮对话 * @param message 用户问题. * @return AI 答案. */ String multiCompletion (String message) ;
@Override public String multiCompletion (String message) { throw new RuntimeException(INFO_PREFIX + Thread.currentThread().getStackTrace()[2 ].getMethodName()); }
@Override public String multiCompletion (String message) { throw new RuntimeException(INFO_PREFIX + Thread.currentThread().getStackTrace()[2 ].getMethodName()); }
/** * 多轮聊天应用 * * @param message * @return */ @GetMapping ("/multi" )public String multi (@RequestParam String message) { String completion = tongYiMultiServiceImpl.multiCompletion(message); return completion; }
html ><html > <head > <meta charset ="UTF-8" > <script src ="js/marked.min.js" > script > <title > SCA AI Example Fronttitle > <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; } .message { margin-bottom : 10px ; padding : 10px ; background-color : #f1f1f1 ; border-radius : 3px ; } .user-message { background-color : #2ecc71 ; color : #fff ; } .bot-message { background-color : #3498db ; 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 > Spring Cloud Alibaba AIh1 > <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 ><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 user-message" ; userMessage.textContent = "用户: " + message; chatBox.appendChild(userMessage); chatBox.scrollTop = chatBox.scrollHeight; loader.style.display = "block" ; var xhr = new XMLHttpRequest(); xhr.open("GET" , "http://localhost:8081/ai/example?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 >
输入一个问题,回答后接着第一个问题继续提问
输入文字,最后输出图片
// 生成图片 ImageResponse genImg (String imgPrompt) ;
@Override public ImageResponse genImg (String imgPrompt) { throw new RuntimeException(INFO_PREFIX + Thread.currentThread() .getStackTrace()[2 ].getMethodName() + INFO_SUFFIX); }
@Override public ImageResponse genImg (String imgPrompt) { throw new RuntimeException(INFO_PREFIX + Thread.currentThread() .getStackTrace()[2 ].getMethodName() + INFO_SUFFIX); }
/** * 文生图应用 * @param imgPrompt * @return */ @GetMapping ("/img" )public String genImg (@RequestParam(value = "prompt" , defaultValue = "Painting a picture of blue water and blue sky." ) String imgPrompt) { ImageResponse imageResponse = tongYiImgService.genImg(imgPrompt); String url = imageResponse.getResult().getOutput().getUrl(); return url; }
<div id ="app" > <template > <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 >template >div > <script > new Vue({ el : "#app" , data : { imgtext : '' ,//图片输入问题 imgresponse : '' ,//图片返回结果 }, methods : { //生成图片 fetchAnswer : function ( ) { var vm = this ; axios.get("http://localhost:8081/ai/img?prompt=" + this .imgtext).then(function (response ) { vm.imgresponse = response.data; }).catch(function (error ) { console .log(error); }); }, } });script >
输入文字,转换成语音,且用语音回答答案
// 生成音频 String genAudio (String text) ;
@Override public String genAudio (String text) { throw new RuntimeException(INFO_PREFIX + Thread.currentThread() .getStackTrace()[2 ].getMethodName() + INFO_SUFFIX); }
@Override public String genAudio (String text) { throw new RuntimeException(INFO_PREFIX + Thread.currentThread() .getStackTrace()[2 ].getMethodName() + INFO_SUFFIX); }
/** * 文字问题输入语音文字输出 * @param message * @param request * @param response * @return */ @GetMapping ("/audio/speech" )public void genAudio (@RequestParam(value = "prompt" ) String prompt, HttpServletRequest request, HttpServletResponse response) { String audio = tongYiAudioService.genAudio(prompt); try { 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(); } catch (IOException e) { throw new RuntimeException(e); } } /** * 文字输入语音输出答案 * @param message * @param request * @param response * @return */ @GetMapping ("/exampleToMp3" )public void exampleToMp3 (@RequestParam(value = "message" , defaultValue = "Tell me a joke" ) String message,HttpServletRequest request,HttpServletResponse response) { String completion = tongYiSimpleService.completion(message); String audio = tongYiAudioService.genAudio(completion); try { 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(); } catch (IOException e) { throw new RuntimeException(e); } }
<div id ="app" > <template > <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 >template >div > <script > new Vue({ el : "#app" , data : { mp3text :'' ,//语音输入问题 mp3response :'' ,//语音返回结果 mp3text2response :'' //文字输入语音输出结果 }, methods : { //文字转语音 Mp3Answer : function ( ) { var vm = this ; axios({ url :'http://localhost:8081/ai/audio/speech?prompt=' +this .mp3text, responseType :'blob' }).then(result => { vm.mp3response = window .URL.createObjectURL(result.data); }) //文字输出结果 axios({ url :'http://localhost:8081/ai/exampleToMp3?message=' +this .mp3text, responseType :'blob' }).then(result => { vm.mp3text2response = window .URL.createObjectURL(result.data); }) } } });script >
以上就是一些基本案例。