⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/qq_34742146/article/details/140503128 「星空宇航员」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

Spring AI简介

Spring AI是一个面向AI工程的应用框架。其目标是将可移植性和模块化设计等设计原则应用于AI领域的Spring生态系统, 转换为人话来说就是:Spring出了一个AI框架,帮助我们快速调用AI,从而实现各种功能场景。

但是重点:对于国内开发者不太友好已经不太支持了。于是乎Spring Cloud Alibaba AI出世了!

Spring Cloud Alibaba AI 简介

Spring Cloud Alibaba AI 基于 Spring AI 0.8.1 版本完成通义系列大模型的接入。DashScope灵积模型服务建立在 模型即服务(Model-as-a-Service,MaaS)的理念基础之上,围绕AI各领域模型,通过标准化的API提供包括模型推理、模型微调训练在内的多种模型服务。

目前支持的模型主要有:对话、文生图、文生语音,更多功能特性正在适配中。那以上介绍完之后咱们就完成一些案例来看看效果吧

开发环境

这里说下我本地的环境,阿里要求JDK为17+

JDK17,Maven3.5以上,Spring Boot2.0+,Spring Cloud2021+

创建工程

创建父工程

创建项目就是正常的Maven项目

  • 引入依赖
<?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>

<groupId>com.tongyi</groupId>
<artifactId>tongyi2</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>aliai</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17</java.version>
<spring-boot.version>2.7.18</spring-boot.version>
<spring-cloud.version>2021.0.8</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
</properties>

<!-- springboot、springcloud、springcloud alibaba-->
<dependencyManagement>
<dependencies>
<!-- SpringCloud 微服务 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<!-- SpringCloud Alibaba 微服务 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<!-- SpringBoot 依赖配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

</project>

创建子工程

创建子工程就是正常的maven项目(选中父工程右键)

  • 引入依赖
<?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">
<parent>
<artifactId>tongyi2</artifactId>
<groupId>com.tongyi</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>aliai</artifactId>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-ai</artifactId>
<version>2023.0.1.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>


</dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.18</version>
<configuration>
<mainClass>com.usian.AliApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
  • 添加配置文件

主要配置阿里云申请的api-key:

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;
}
  • 编写前端
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="js/marked.min.js"></script>
<title>SCA AI Example Front</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 {
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 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>

<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>
  • 测试

以上就是一些基本案例。

文章目录
  1. 1. Spring AI简介
  2. 2. Spring Cloud Alibaba AI 简介
  3. 3. 开发环境
  4. 4. 创建工程
    1. 4.0.0.1. 创建父工程
    2. 4.0.0.2. 创建子工程
  • 5. 案例
    1. 5.0.0.1. 单轮对话
    2. 5.0.0.2. 多轮对话
    3. 5.0.0.3. 文生图
    4. 5.0.0.4. 文生语音