作品简介:
当今快速发展的AI时代,学会使用AI的同时,也可以融入AI,来打造自己的产品,我给我这个取名M-聪明, 是基于VUE 3 + Spring Boot -Redis +ChatGML + RxJava + SSE 的AI 服务平台。 然后这款工具旨在为用户提供便捷、高效的AI服务体验,无论是进行日常对话、创作设计作品,还是处理大量文档资料,都能轻松应对。在开发过程中,通过腾讯云AI代码助手的强大支持,不仅仅提高了开发效率,还帮助自己解决了许多问题!!!
技术架构
开发工具:
- 前端: Visual Studio Code
- 后端IDE:IntelliJ IDEA 2023.1.3
- 腾讯云AI代码助手
前端:
- Vue 3
- Vue-CLl 脚手架
- Axios 请求库
- EleMent-UI 组件库
- OpenAPI 前端代码生成
后端:
- 存储层:MySQL 数据库 +Redis 缓存+ 腾讯云 COS 对象存储
- MyBatis-Plus及MyBatisX自动生成
- Redission 分布式锁
- Caffeine 本地缓存
- 基于 ChatGLM 大模型实现 AI 能力
- RxJava 响应式框架+多线程/线程池实战
- Shardingsphere 分库分表+分布式 ID 雪花算法
- SSE 服务端推送
- 多种设计模式
- 多角度项目优化:性能、稳定性、幂等性优化等
架构设计:
实现过程
开发环境,开发流程
开发环境:
后端:JDK17安装 ,Myslq版本8.x版本,Redis 5.X版本
前端:node.js 18.x版本 npm 9.X版本
工具 :腾讯云AI代码助手
++下载方式: 打开VS Code,左侧导航上点击扩展,然后搜索腾讯云AI代码助手 -> 点击安装++
开发流程 :
首先进行需求分析,明确功能点和性能指标;技术选型 -> 然后进行系统设计,包括模块划分、接口定义等;然后写Demo -> 写代码(实现业务逻辑),按照敏捷开发的方式,迭代开发并测试;最后进行系统集成和部署,确保整体功能的正常运行。其中通过腾讯云AI代码助手来便捷开发,大大提升开发效率!
关键技术解析
这里简单解析某一个环节,一个通用的场景,实现流式回答,后端实时获取数据返回给前端,而不是让前端用户一直等待全部在一起返回,体验感更好! 核心技术:这里后端java 通过RxJava 响应式编程和SSe技术实时数据传输完成:
RXJava:RxJava 定个基于事件驱动的利用可观察序列来实现异步编程的一个类库,是响应式编程在 Java 语言上的实现。
1、事件驱动
事件可以是任何事情,如用户的点击操作、网络请求的结果、文件的读写等。事件驱动的编程模型是通过事件触发行动。
比如前端开发中,用户点击按钮后会进行弹窗,这就是"点击事件"触发了"弹窗行动"
// 前端按钮点击
btn.onClick(()->{
// 弹窗
showModal();
})
在 RxJava 中,事件可以被看作是数据流中的数据项,称为"事件流"或"数据流"。每当一个事件发生,这个事件就会被推送给那些对它感兴趣的观察者(Observers)。
2、可观测序列
可观测序列是指一系列按照时间顺序发出的数据项,可以被观察和处理。可观测序列提供了一种将数据流和异步事件建模为一系列可以订阅和操作的事件的方式。
可以理解为在数据流的基础上封装了一层,多加了一点方法。
RxJava 的核心知识点
RxJava 是基于 观察者模式 实现的,分别有观察者和被观察者两个角色,被观察者会实时传输数据流,观察者可以观测到这些数据流。
在 RxJava 中,观察者就是 Observer,被观察者是 Observable 和 Flowable。
Observable和Flowable 区别:
Observable 适合处理相对较小的、可控的、不会迅速产生大量数据的
场景。它不具备背压处理能力,也就是说,当数据生产速度超过数据
消费速度时,可能会导致内存溢出或其他性能问题
Flowable 是针对背压(反向压力)问题而设计的可观测类型。背压问
题出现于数据生产速度超过数据消费速度的场景。Flowable 提供了多
种背压策略来处理这种情况,确保系统在处理大量数据时仍然能够保
持稳定。
当然springAI 中是Spring WebFlux其实原理都差不多! 然后这里我用RxJava:
Flowable 是针对背压(反向压力)问题而设计的可观测类型。背压问题出现于数据生产速度超过数据消费速度的场景。Flowable 提供了多种背压策略来处理这种情况,确保系统在处理大量数据时仍然能够保持稳定。
事件:
RxJava 也是一个基于事件驱动的框架,我们来看看一共有哪些事件,分别在什么时候触发:
1)onNext,被观察者每发送一次数据,就会触发此事件。
2)onError,如果发送数据过程中产生意料之外的错误,那么被观察者可以发送此事件。
3)onComplete,如果没有发生错误,那么被观察者在最后一次调用 onNext 之后发送此事件表示完成数据传输。
java
flowable.observeOn(Schedulers.io())
.doOnNext(item -> {
System.out.println("来数据啦" + item.toString());
})
.doOnError(e -> {
System.out.println("出错啦" + e.getMessage());
})
.doOnComplete(() -> {
System.out.println("数据处理完啦");
}).subscribe();
更多可以查看官网 https://reactivex.io/,支持多种不同的编程语言。
后续这些会单独一篇文章来详细描述他们!!!
Demo 演示:
1.引入依赖:
java
<dependency>
<groupId>org.reactivestreams</groupId>
<artifactId>reactive-streams</artifactId>
<version>1.0.4</version>
</dependency>
2.编写单元测试:
java
@Test
void rxJavaDemo() throws InterruptedException {
// 创建一个流,每秒发射一个递增的整数(数据流变化)
Flowable<Long> flowable = Flowable.interval(1, TimeUnit.SECONDS)
.map(i -> i + 1)
.subscribeOn(Schedulers.io()); // 指定创建流的线程池
// 订阅 Flowable 流,并打印每个接受到的数字
flowable.observeOn(Schedulers.io())
.doOnNext(item -> System.out.println(item.toString()))
.subscribe();
// 让主线程睡眠,以便观察输出
Thread.sleep(10000L);
}
前后端实时通讯:
有多种方案:可以轮询 :前端间隔一定时间就
java
data: First message\n
\n
data: Second message\n
\n
data: Third message\n
id: 3\n
\n
retry: 10000\n
data: Fourth message\n
\n
调用后端提供的结果接口,比如 200ms 一次,后端处理一些结果就累加放置在缓存中。
WebSocket:全双工协议,前端能实时推送数据给后端(或者从后端缓存拿数据),后端也可以实时推送数据给前端。 当然在这里有点重了。我们只需要服务端给用户端推送即可所有:
SSE(后端推送给前端) 前端发送请求并和后端建立连接后,后端可以实时推送数据给前端,无需前端自主轮询。
SSE:
基本概念:
服务器发送事件(Server-Sent Events)是一种用于从服务器到客户端的 单向、实时 数据传输技术,基于 HTTP协议实现。
特点:
- 单向通信:SSE 只支持服务器向客户端的单向通信,客户端不能向服务器发送数据。
- 文本格式:SSE 使用 纯文本格式 传输数据,使用 HTTP 响应的
text/event-stream
MIME 类型。 - 保持连接:SSE 通过保持一个持久的 HTTP 连接,实现服务器向客户端推送更新,而不需要客户端频繁轮询。
- 自动重连:如果连接中断,浏览器会自动尝试重新连接,确保数据流的连续性。
SSE 数据格式
SSE 数据流的格式非常简单,每个事件使用 data
字段,事件以两个换行符结束。还可以使用 id
字段来标识事件,并且 retry
字段可以设置重新连接的时间间隔。
自主实现 SSE
实现 SSE 非常简单,无论是 Java 服务端还是前端 HTML5 都支持了 SSE
因为后端是Spring项目,接给请求返回 SseEmitter 对象即可。(Get请求!!)
示列:
java
@GetMapping("/sse")
public SseEmitter testSSE() {
// 建立 SSE 连接对象,0 表示不超时
SseEmitter emitter = new SseEmitter(0L);
... 业务逻辑处理
return emitter;
}
前端:
可以使用 JavaScript 的 EventSource
对象来连接和处理服务器发送的事件。示例代码:
javascript
// 创建 SSE 请求
const eventSource = new EventSource(
"http://localhost:8080/sse"
);
// 接收消息
eventSource.onmessage = function (event) {
console.log(event.data);
};
// 生成结束,关闭连接
eventSource.onerror = function (event) {
if (event.eventPhase === EventSource.CLOSED) {
eventSource.close();
}
};
整体部分Demo样列:
javascript
@GetMapping("/glm")
public SseEmitter getAnswer(String fileType, String Message) throws IOException {
log.info("开始生成回答,{}", Message);
// 创建一个SseEmitter对象,用于发送服务器发送事件(SSE)
SseEmitter sseEmitter = new SseEmitter(0L);
// 获取文件URL,拼接本地地址和文件名
String FileUrl = fileProperties.getUrl() + fileType;
// 调用AI服务,根据文件类型和消息生成流式结果
Flowable<ModelData> streamResult = aiResult.doSendMessageByDocument(FileUrl, Message);
// 观察流式结果,并在IO线程上处理
streamResult
.subscribeOn(Schedulers.io()) // 指定流式数据的时候用的线程池
.observeOn(Schedulers.io()) // 指定观察者使用的线程池 去执行方法
.doOnNext(data -> {
// 打印AI返回的数据内容
System.out.println(data.getChoices().get(0).getDelta().getContent());
// 将数据转换为JSON字符串并通过SSE发送给客户端
sseEmitter.send(JSONUtil.toJsonStr(data.toString()));
})
.doOnError(e -> {
// 如果发生错误,记录错误信息
log.info("SSEE 错误 ", e);
})
.doOnComplete(sseEmitter::complete) // 当流完成时,通知SSE发射器完成
.subscribe(); // 订阅流
return sseEmitter;
}
sendQuestion() {
this.eventSource = new EventSource(
`http://xxxx:xxxx/ai/charGlmSee?message=${encodeURIComponent(this.newIput)}`
);
this.messages.push({ type: "bot", content: "ai", theData: ["Loading..."] });
const lastBotMessageIndex = this.messages.length - 1;
this.eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
const newMessage = data.choices[0].delta.content;
this.aiMessage.push(newMessage);
this.messages[lastBotMessageIndex].theData = this.aiMessage;
this.$nextTick(() => {
this.$refs.chatHistory.scrollTop = this.$refs.chatHistory.scrollHeight;
});
};
this.eventSource.onerror = (error) => {
if (error.eventPhase === EventSource.CLOSED) {
this.eventSource.close();
}
};
},
腾讯云AI代码助手便捷开发:
代码助手,其优秀的代码补全功能:
- 腾讯云AI代码助手能够根据开发者输入的代码片段,预测并补全剩余的代码,你只需要TAB键选择,这大大减少了代码时间和语法错误,提生开发效率。
- 它支持多种编程语言的补全,如Python、JavaScript/TypeScript、Java、C/C++、Go等。
- 补全的代码不仅准确,而且符合开发者的编码风格和习惯。
代码诊断与优化:
AI代码助手能够实时检查代码中的语法错误和逻辑错误,帮助即使发现问题并进行修正。
它还能提供代码优化的建议,如简化复杂的逻辑结构、替换低效的算法等,使代码更加高效和优雅。非常方便!!!
并且也可以实现代码评审:
帮助你修改代码
技术对话与知识支持:
腾讯云AI代码助手将聊天功能与IDE进行了集成,开发者可以随时随地与AI进行技术对话咨询。
通过对话,开发者可以获取代码编写的建议、解决技术难题,甚至获取示例代码。
这个经常使用,比如你不想写代码,直接问助手,我写通过什么框架,写什么,有哪些组件,描述清除,AI助手帮你写,不够完善,可以继续问,也可以自己简单修改,描述越清除,效果越好!!!
而且对你写好的代码如果有疑问,问题修改,可以直接复制代码,提出问题,助手直接给出相关修改后代码非常详细!!!
这种交互方式使得开发者能够更快速地掌握新技术和框架。
过程中问答的一些:
代码注释与解释:
AI代码助手能够根据代码生成相应的注释,这个就太棒了,不用手写文档了。舒服。一键上传,而且排版还好看,详细!!!帮助开发者更好地理解代码的功能和逻辑。
当开发者需要处理别人的代码或在既有代码中进行延展开发时,AI代码助手可以快速解释初始代码,降低理解成本。
单元测试生成:
AI代码助手能够根据函数、方法、内容逻辑生成相关的测试代码。
它还能根据我们的的代码习惯,自动推荐单元测试的编写,提高单元测试的覆盖率。
使用说明
根据界面的操作提问,访问M-聪明网址,选择你需要的功能板块,提出问提,等待AI回答!!
效果展示
部分功能展示:
M-聪明-M_AI(后续慢慢扩张和优化)
总结: 其主要是核心是学会利用AI代码辅助工具,来快速帮助我们开发。辅助工具有很多,我这里主要是使用的腾讯云AI代码助手,在其过程中,我们可以快速方便问助手,来帮助我们实时解决问题,其中也会有详细的解决方案同时,还有解析,帮助我们过程化学习。以及其代码设计优化,提升,规范开发,代码提示,一键引用等操作,非常方便。还有文档生成,这不大大减少了这些人力时间,可以着重开发核心项目块了嘛,对不想敲字的是非常方便。开发少不了测试,也可以帮助我们测试等这些操作都是简化一些繁琐开发,其我们重心只需要放在业务逻辑上即可!!!大大提示开发效率了。