vue+java实现简易AI问答组件(基于百度文心大模型)

一、需求

公司想要在页面中加入AI智能对话功能,故查找免费gpt接口,最终决定百度千帆大模型(进入官网、官方文档中心);

二、主要功能列举

  • AI智能对话;
  • 记录上下文回答环境;
  • 折叠/展开窗口;
  • 可提前中止回答;
  • 回答内容逐字展示并语音播报;

三、效果图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、技术选型

1、前端环境

  • node(14.21.3)
  • VueCli 2
  • element-ui(^2.15.14)
  • axios
  • node-sass(^4.14.1)
  • sass-loader(^7.3.1)
  • js-md5(^0.8.3)

2、后端环境

  • JDK8
  • springboot

五、声明

  • 本文章以及源码纯粹自己写着玩,等于是个demo,有许多需要完善和优化的地方,仅供大家参考,有错误的地方欢迎大家批评指正~~
  • 由于作者其实是java,所以前端代码中如果看到神奇的地方,希望大家包涵,哈哈哈哈

四、百度千帆大模型应用创建

1、访问官网,注册账号并登录;

2、选择“应用接入”-“创建应用”

在这里插入图片描述
进去填一个应用名及描述即可,服务默认全勾选上;

3、保存后返回应用列表,获取api key和secret key

在这里插入图片描述

PS:

百度提供的大模型服务有好多种,我此处是白嫖的其中一个免费的,如下图:
其中ERNIE开头的是百度自己的,文心一言用的就是这种,其他有些是三方大模型;
在这里插入图片描述

具体不同服务之间有什么区别可以看官方介绍,个人觉得免费的几个主要在于轻量等级、响应速度、回答内容复杂程度、可保存的上下文大小等几个方面;

五、部分后台代码

1、官网下载java sdk或者引入百度千帆pom

官放文档地址:https://cloud.baidu.com/doc/WENXINWORKSHOP/s/7ltgucw50
java SDK地址:https://github.com/baidubce/bce-qianfan-sdk/tree/main/java
maven仓库地址:https://mvnrepository.com/artifact/com.baidubce/qianfan

POM:

<!-- https://mvnrepository.com/artifact/com.baidubce/qianfan -->
<dependency><groupId>com.baidubce</groupId><artifactId>qianfan</artifactId><version>0.0.4</version>
</dependency>

2、创建springboot项目,并导入sdk或引入千帆pom

此处是把sdk导入到工程中;

3、项目代码结构如下

在这里插入图片描述

pom.xml :

<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.baidu</groupId><artifactId>aichat</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><name>aichat</name><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.9</version></parent><dependencies><!-- SpringBoot的依赖配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.2.13.RELEASE</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.10.1</version></dependency><dependency><groupId>org.apache.httpcomponents.client5</groupId><artifactId>httpclient5</artifactId><version>5.3.1</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.1.1.RELEASE</version><configuration><fork>true</fork> <!-- 如果没有该配置,devtools不会生效 --></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><version>3.1.0</version><configuration><failOnMissingWebXml>false</failOnMissingWebXml><warName>${project.artifactId}</warName></configuration></plugin></plugins><finalName>${project.artifactId}</finalName></build></project>

AiChatController.java:

package com.baidubce.controller;import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import com.baidubce.qianfan.Qianfan;
import com.baidubce.qianfan.core.builder.ChatBuilder;
import com.baidubce.qianfan.model.chat.ChatResponse;
import com.baidubce.qianfan.model.chat.Message;
import com.baidubce.utils.JsonUtils;
import com.baidubce.utils.SecUtils;@RestController
public class AiChatController {private static final String accessKey = "你创建的应用的API Key";private static final String secretKey = "你创建的应用的Secret Key";private static Qianfan qianfan = new Qianfan("OAuth", accessKey, secretKey);/*** 	参数:* 		messages: 对话记录,role:user是用户,assistant是AI,如:[{"role":"user","content":"1"},{"role":"assistant","content":"“1”是一个数字。"},{"role":"user","content":"你是"},{"role":"assistant","content":""}]* 		timestamp:请求毫秒值,1717742825695* 		signature: 签名,4bc9c3b8dbe4de5bc924b6fa0506c606* @author x轩* @version 2024年6月7日 下午2:46:32*/@PostMapping("/sendMsg")public String sendMsg(@RequestBody Map<String, Object> params) {// 验签,我自己加的,防止恶意调用,作用不大,提高门槛而已if(!checkSign(params)) {return "签名不正确!";}String result = null;try {result = chat(String.valueOf(params.get("messages")));} catch (Exception e) {e.printStackTrace();return "接口繁忙,请稍后再试!";}return result;}/*** 	参数:* 		messages: 业务参数* 		timestamp:请求毫秒值* 		signature: 签名* *	加签规则:*		要求1:timestamp和当前系统时间不能超过5秒钟*		要求2:MYCHAT|timestamp|messages拼接后MD53次加密** @author x轩* @version 2024年6月6日 下午4:13:03*/private boolean checkSign(Map<String, Object> params) {String timestamp = String.valueOf(params.get("timestamp"));String messages = String.valueOf(params.get("messages"));String signature = String.valueOf(params.get("signature"));if(StringUtils.isAnyBlank(timestamp, messages, signature)) {return false;}// 1.判断时间if((System.currentTimeMillis()- Long.valueOf(timestamp))>5000) {// 过期return false;}// 2.验签String p = "MYCHAT|"+timestamp+"|"+messages;String md5of3 = SecUtils.encoderByMd5With32Bit(SecUtils.encoderByMd5With32Bit(SecUtils.encoderByMd5With32Bit(p)));if(!signature.equalsIgnoreCase(md5of3)) {return false;}return true;}public static void main(String[] args) {
//        chat("对于调休你怎么看");chatStream("介绍一下自己");}private static String chat(String messages) {ChatBuilder bulder = qianfan.chatCompletion()
//        		.model("ERNIE-Speed-128K")
//        		.model("ERNIE-Speed-8K").model("ERNIE-Tiny-8K");List<Message> messageList = JsonUtils.readValues(messages, Message.class);// 过滤一下,去除空内容对象messageList = messageList.stream().filter(m->{return StringUtils.isNotBlank(m.getContent());}).collect(Collectors.toList());for(Message m : messageList) {bulder.addMessage(m);}ChatResponse response = bulder.execute();return response.getResult();}private static void chatStream(String message) {Iterator<ChatResponse> stream = qianfan.chatCompletion()
//		.model("ERNIE-Speed-128K")
//		.model("ERNIE-Speed-8K").model("ERNIE-Tiny-8K").addMessage("user", message).executeStream();while(stream.hasNext()) {System.out.println(stream.next().getResult());}}
}

六、 Vue部分代码

1、vue.config.js

const port = process.env.port || process.env.npm_config_port || 80 // 端口module.exports = {lintOnSave: false,publicPath: "/aichat-front",assetsDir: 'static',// 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。productionSourceMap: false,devServer: {host: '0.0.0.0',port: port,open: true,proxy: {['/aichat']: {target: `http://127.0.0.1:8080/aichat`,changeOrigin: true,pathRewrite: {['^/aichat']: ''}},},},
}

2、App.vue

<template><div id="app"><qian-fan-chat/></div>
</template><script>
import QianFanChat from './components/QianFanChat'export default {name: 'App',components: {QianFanChat}
}
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;
}
</style>

3、@/components/QianFanChat组件

<template><div class="chat-div"><div v-show="showChatBox" class="chat-main"><div id="messagediv" class="messagediv"><div class="item"><img class="avatar" :src="aiAvatar" ><div class="answerDiv"><p>我是AI智能小助手,有问题请咨询我吧!</p></div></div><div v-for="(item, index) in messageList" class="item"><img v-if="item.role=='assistant'" class="avatar" :src="aiAvatar" ><img v-if="item.role=='user'" class="avatar" :src="userAvatar" ><div class="answerDiv"><p v-if="!item.loading" v-html="item.content"></p><p v-else>思考中 <i class="el-icon-loading"></i></p><a v-if="index==messageList.length-1 &&item.role=='assistant' && (loading || speaking)" href="#" @click="stopAnswer">停止回答</a></div></div></div><div class="sendDiv"><el-input @keyup.enter.native="getAnswer" v-model="question" placeholder="输入中医药相关内容搜一搜"></el-input><el-button @click="getAnswer"><i class="el-icon-s-promotion"></i></el-button></div></div><div v-show="showChatBox" class="close-btn" @click="showChatBox=false"><i class="el-icon-close"></i></div><div v-show="!showChatBox" class="small-window" @click="showChatBox=true">AI问答</div></div>
</template>
<script>
const msg = new SpeechSynthesisUtterance();import { sendMsg } from '@/api/aichat';
import { sign } from '@/utils/securityUtil'
import aiAvatar from '@/assets/images/ai-avatar.jpg';
import userAvatar from '@/assets/images/user-avatar.jpg';export default {name: 'QianFanChat',data(){return {showChatBox: false,loading: false,speaking: false,aiAvatar,userAvatar,question:'',messageList:[],// 逐字输出 STARTtimer: null,length: 0,index: 0,// 逐字输出 END}},mounted(){},methods: {getAnswer(){if(this.loading){this.$message({type: 'warning', message:'正在回答,请耐心等待!'});return;}if(!this.question.trim()){this.$message({type: 'warning', message:'请输入内容!'});return;}this.loading = true;let tmpQustion = this.question;this.question = '';this.messageList.push({ role:'user', content: tmpQustion, loading: false });this.messageList.push({ role:'assistant', content: '' , loading: true});this.$nextTick(()=>{this.scroll();})let params = {messages: JSON.stringify(this.messageList)};params.timestamp = new Date().getTime();params.signature = sign(params);sendMsg(params).then(res=>{// 判断loading是否被中断(停止回答可中断)if(!this.loading){// 点击了“停止回答”return;}// 接口请求完毕,替换最后一条内容this.messageList[this.messageList.length-1].loading = false;this.index = 0;this.length = res.length;this.handleSpeak(res);// 一个字一个字给我蹦this.timer = setInterval(()=>{if(this.index<=this.length-1){let word = res.charAt(this.index);if(word=='\n'){word = '<br>'}this.messageList[this.messageList.length-1].content += word;this.index++;}else{// 结束this.loading = false;clearInterval(this.timer);}this.scroll();}, 30);})},scroll(){messagediv.scrollTo({top: messagediv.scrollHeight,})},stopAnswer(){this.handleStop();clearInterval(this.timer);this.length = 0;this.index = 0;this.loading = false;// 判断最后一条内容是不是空,是则给上默认输出let lastMsg = this.messageList[this.messageList.length-1];if(!lastMsg.content){lastMsg.loading = false;lastMsg.content = '请继续向我提问吧!';}},// 语音播报的函数handleSpeak(text) {this.handleStop();this.speaking = true;// 处理多音字msg.text = text;     // 朗读内容msg.lang = "zh-CN";  // 使用的语言:中文 msg.volume = 0.5;      // 声音音量:1  设置将在其中发言的音量。区间范围是0到1,默认是1msg.rate = 1.6;        // 语速:1  设置说话的速度。默认值是1,范围是0.1到10,表示语速的倍数,例如2表示正常语速的两倍msg.pitch = 1.5;       // 音高:2  设置说话的音调(音高)。范围从0(最小)到2(最大)。默认值为1// msg.voiceURI = 'Google 普通话(中国大陆)';msg.onstart = (e)=>{};msg.onend = (e)=>{this.speaking = false;};msg.onboundary = (e) => {}speechSynthesis.speak(msg);    // 播放},// 语音停止handleStop(e) {this.speaking = false;msg.text = e;msg.lang = "zh-CN";speechSynthesis.cancel(msg);},}
}
</script>
<style lang="scss" scoped>::v-deep {.el-input {width: 270px;input {background-color: rgba(0,0,0,.5);border: none;color: white;}}.el-button {background-color: rgba(0,0,0,.5);border: none;margin-left: 10px;padding: 0 20px;i {font-size: 20px;color: white;}&:focus {background-color: rgba(0,0,0,.5);}&:hover {background-color: white;i {color: black;}}}}.chat-div {position: absolute;top: 0;left: 0;display: flex;z-index: 99;cursor: pointer;.close-btn {margin-top: 18px;color: white;background-color: rgba(0, 0, 0, .6);height: 30px;width: 30px;text-align: center;line-height: 30px;border-radius: 50%;}.small-window {color: white;margin-top: 18px;padding: 10px;background-color: rgba(16, 168, 129, .8);width: 26px;font-size: 20px;border-top-right-radius: 10px;border-bottom-right-radius: 10px;}}.chat-main {border-radius: 4px;margin: 10px 0;padding: .1rem .1rem;width: 374px;.messagediv {overflow: auto;max-height: 60vh;.item {display: flex;margin-bottom: .1rem;.avatar {width: 40px;height: 40px;}.answerDiv {p {color: white;background-color: rgba(0, 0, 0, .6);padding: 10px;margin: 0 10px;font-size: 16px;border-radius: 6px;text-align: left;}a {cursor: pointer;font-size: 15px;color: red;text-decoration: underline;margin-left: 10px;font-weight: bold;}}}&::-webkit-scrollbar {width: 0;}}.sendDiv {display: flex;justify-content: end;margin: 10px 10px 0 0;}}
</style>

4、@/utils/request.js

import axios from 'axios'
import { Notification, MessageBox, Message } from 'element-ui'axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({// axios中请求配置有baseURL选项,表示请求URL公共部分baseURL: process.env.VUE_APP_BASE_API,// 超时timeout: 50000
})
// request拦截器
service.interceptors.request.use(config => {// get请求映射params参数if (config.method === 'get' && config.params) {let url = config.url + '?';for (const propName of Object.keys(config.params)) {const value = config.params[propName];var part = encodeURIComponent(propName) + "=";if (value !== null && typeof (value) !== "undefined") {if (typeof value === 'object') {for (const key of Object.keys(value)) {if (value[key] !== null && typeof (value[key]) !== 'undefined') {let params = propName + '[' + key + ']';let subPart = encodeURIComponent(params) + '=';url += subPart + encodeURIComponent(value[key]) + '&';}}} else {url += part + encodeURIComponent(value) + "&";}}}url = url.slice(0, -1);config.params = {};config.url = url;}return config
}, error => {console.log(error)Promise.reject(error)
})// 响应拦截器
service.interceptors.response.use(res => {return res.data;},error => {console.log('err' + error)let { message } = error;if (message == "Network Error") {message = "后端接口连接异常";}else if (message.includes("timeout")) {message = "系统接口请求超时";}else if (message.includes("Request failed with status code")) {message = "系统接口" + message.substr(message.length - 3) + "异常";}Message({message: message,type: 'error',duration: 5 * 1000})return Promise.reject(error)}
)export default service

5、@/utils/securityUtil.js

PS: 由于这个项目不需要登录,我又怕接口泄露导致别人恶意调用,所以给接口加了个签名,具体策略大家可以自定义(讲真的,没什么用,前台加签别人打开调试模式照样可以看到加签策略。。。为了应对这个情况,我把前台加签JS给做了个混淆,算是增加一下门槛吧;还可以禁止用户点击F12和右键事件【具体代码见此篇文章】)

// 加签方法,方法接收两个参数: timestamp和messages(消息JSON字符串),返回签名;已混淆,以下代码具体签名策略如下:固定字符串"MYCHAT"、时间戳、消息体用|拼接后进行3次MD5加密:如MYCHAT|1718181053994|[{"role":"user","content":"1"},{"role":"assistant","content":"“1”是一个数字。"}]
const _0x4e66=['MYCHAT','timestamp'];const _0x3524=function(_0x4e6602,_0x35247b){_0x4e6602=_0x4e6602-0x0;let _0x2ee47d=_0x4e66[_0x4e6602];return _0x2ee47d;};import _0x50d0de from'js-md5';export function sign(_0x5c789a){let _0x1bf721='|'+_0x5c789a[_0x3524('0x1')];let _0x202f97='|'+_0x5c789a['messages'];let _0x74f806=_0x3524('0x0')+_0x1bf721+_0x202f97;_0x74f806=_0x50d0de(_0x74f806);_0x74f806=_0x50d0de(_0x74f806);_0x74f806=_0x50d0de(_0x74f806);return _0x74f806;}

6、@/api/aichat.js

import request from '@/utils/request'export function sendMsg(data) {return request({url: '/sendMsg',method: 'post',data: data})}

有问题或者需要完整项目源码的话私聊吧,关机下班底薪到手~

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

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

相关文章

使用MATLAB对地铁站、公交站等求解最短路径

使用MATLAB对城市的地铁站、公交站等站点&#xff0c;根据站点的经纬度坐标和彼此之间的权重&#xff0c;求解其最短路径、途径站点和路程 已知的数据如图&#xff0c;是西安市地铁站点的数据&#xff0c;保存在一个Excel里 如图&#xff0c;每列的内容都在上面&#xff0c;不…

滚动条样式

/*滚动条*/ //滚动条没有滑块的轨道部分. ::-webkit-scrollbar-track-piece {background: #fff;border-radius: 0px;opacity: 1;border: 1px solid #D9D9D9; } //整个滚动条 ::-webkit-scrollbar {width: 8px;height: 8px;background-color: transparent; } //滚动条上的滚动滑…

经常加班却不给加班费,我又不想离开这个单位,该怎么办?

经常加班却不给加班费&#xff0c;我又不想离开这个单位&#xff0c;该怎么办&#xff1f; --#李秘书讲写作#教你如何在维护权益与保持工作稳定间找到平衡&#xff1f; 在现代社会中&#xff0c;加班已经成为许多职场人士的常态。你也许也不例外&#xff0c;每天都在忙碌的工作…

用idea将java文件打成jar包

一、用idea将java文件打成jar包 1、在idea上选择file—Project Structure 2、Artifacts —点–JAR—From modules with dependencies 3、选择要打包的java文件 4、Build — Build Artifacts 5、找到刚才添加的Artifacts直接Build 6、生成jar包文件

C语言 | Leetcode C语言题解之第140题单词拆分II

题目&#xff1a; 题解&#xff1a; struct Trie {int ch[26];bool flag; } trie[10001];int size;void insert(char* s, int sSize) {int add 0;for (int i 0; i < sSize; i) {int x s[i] - a;if (trie[add].ch[x] 0) {trie[add].ch[x] size;memset(trie[size].ch, 0…

C语言 | Leetcode C语言题解之第139题单词拆分

题目&#xff1a; 题解&#xff1a; unsigned long long Hash(char* s, int l, int r) {unsigned long long value 0;for (int i l; i < r; i) {value value * 2333ull;value s[i] - a 1;}return value; } bool query(unsigned long long* rec, int len_rec, unsigned…

【代码随想录】【算法训练营】【第30天 1】 [322]重新安排行程 [51]N皇后

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 LeetCode。 day 30&#xff0c;周四&#xff0c;好难&#xff0c;会不了一点~ 题目详情 [322] 重新安排行程 题目描述 322 重新安排行程 解题思路 前提&#xff1a;…… 思路&#xff1a;回溯。 重点&…

抖音a_bogus爬虫逆向补环境

抖音a_bogus爬虫逆向补环境 写在前面 https://github.com/ShilongLee/Crawler 这是我为了学习爬虫而搭建的爬虫服务器项目&#xff0c;目标是作为一个高性能的可靠爬虫服务器为广大爬虫爱好者和安全工程师提供平台进行学习爬虫&#xff0c;了解爬虫&#xff0c;应对爬虫。现已…

Github 2024-06-13开源项目日报Top10

根据Github Trendings的统计,今日(2024-06-13统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目3非开发语言项目2Shell项目1TypeScript项目1Swift项目1PHP项目1Blade项目1JavaScript项目1从零开始构建你喜爱的技术 创建周期:2156…

如何在浏览器书签栏设置2个书签实现一键到达网页顶部和底部

本次设置浏览器为&#xff1a;Chrome浏览器&#xff08;其他浏览器可自行测试&#xff09; 1&#xff0c;随便收藏一个网页到浏览器书签栏 2&#xff0c;右键这个书签 3&#xff0c;修改 4&#xff0c;修改名称 5&#xff0c;修改网址&#xff1a; javascript:(function(…

arm64电源管理之PSCI

PSCIPower State Coordination Interface功耗状态协同接口SCPISystem Control and Power Interface系统控制和电源接口SCMISystem Control and Management Interface系统控制和管理接口SMCCCSMC Calling ConventionSMC调用约定 scpi&#xff1b;通过mailbox核间通信&#xff0c…

借助Historian Connector + TDengine,打造工业创新底座

在工业自动化的领域中&#xff0c;数据的采集、存储和分析是实现高效决策和操作的基石。AVEVA Historian (原 Wonderware Historian) 作为领先的工业实时数据库&#xff0c;专注于收集和存储高保真度的历史工艺数据。与此同时&#xff0c;TDengine 作为一款专为时序数据打造的高…

FullCalendar日历组件集成实战(11)

背景 有一些应用系统或应用功能&#xff0c;如日程管理、任务管理需要使用到日历组件。虽然Element Plus也提供了日历组件&#xff0c;但功能比较简单&#xff0c;用来做数据展现勉强可用。但如果需要进行复杂的数据展示&#xff0c;以及互动操作如通过点击添加事件&#xff0…

怎么防止源代码泄露?9种方法教会你!

怎么防止源代码泄露&#xff1f;首先要了解员工可以通过哪些方式将源代码传输出去&#xff01; 物理方法&#xff1a; — 网线直连&#xff0c;即把网线从墙上插头拔下来&#xff0c;然后和一个非受控电脑直连; — winPE启动&#xff0c;通过光盘或U盘的winPE启动&#xff0c;甚…

Mybatis save、saveOrUpdate、update的区别

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 1. save方法 Mybatis的save方法用于插入一条新的记录。当数据库中不存在相同的记录时&#xff0c;会执行插入操作&#xff1b;如果已经存在相同的记录&#xff0c;则会抛出异常。 int result sqlSession.insert(&…

电脑桌面提醒做事的app 好用的桌面提醒app

在快节奏的现代生活中&#xff0c;我们每天都要通过电脑处理大量的工作事项。然而&#xff0c;繁忙的工作节奏有时会导致我们遗忘某些重要任务&#xff0c;从而带来不必要的损失。为了避免这种情况&#xff0c;选择一款好用的桌面提醒app显得尤为重要。 想象一下&#xff0c;你…

C语言| 数组

直接定义一个数组&#xff0c;并给所有元素赋值。 数组的下标从0开始&#xff0c;下标又表示数组的长度。 【程序代码】 #include <stdio.h> int main(void) { int a[5] {1, 2, 3, 4, 5}; int i; for(i0; i<5; i) { printf("a[%d] %d\…

翻译: Gen AI生成式人工智能学习资源路线图一

Introduction 介绍 本文档旨在作为学习现代人工智能系统背后的关键概念的手册。考虑到人工智能最近的发展速度&#xff0c;确实没有一个好的教科书式的资源来快速了解 LLMs 或其他生成模型的最新和最伟大的创新&#xff0c;但互联网上有大量关于这些主题的优秀解释资源&#x…

蒂姆·库克解释Apple Intelligence和与ChatGPT合作的区别|TodayAI

在2024年全球开发者大会&#xff08;WWDC 2024&#xff09;上&#xff0c;苹果公司首席执行官蒂姆库克&#xff08;Tim Cook&#xff09;隆重介绍了公司的最新人工智能&#xff08;AI&#xff09;计划——Apple Intelligence&#xff0c;并宣布了与OpenAI的ChatGPT的合作。虽然…

定时器0电机控制PWM输出

/*立式不锈钢波纹管机控制板2021 2 26 pcb PAST******/ #include <REG52.H> #include <intrins.H> #define uint unsigned int #define uchar unsigned char #define …