uniapp h5项目AI会话聊天功能的实现

06-01 1391阅读

        最近公司h5项目需要做一个简单的ai聊天功能,用的智普ai。实现过程是将问题发给自家后端,后端返回一个答案获取接口,前端再调用答案接口,获取流式答案,并以类似打字的方式显示到聊天窗口中。

        聊天窗口代码参考的文章1,根据自己的需求稍稍做了调整;流式数据获取参考的文章2,主要是用到了fecthEventSource。感谢两位大神!

        AI接口文档地址:Docs

参考文章:

1、前端对接AI模型接口 实现ChatGPT流式数据并【实现打字效果】和【终止会话】_event:conversation.message.delta-CSDN博客

2、基于uniapp开发的智能客服(接入api,附完整代码)_uni-app 智能客服-CSDN博客 

         上代码:

	
		
			
				
				
			
			
				
				
					
						
						{item.time}} -->
						
							
						
					
					
						{item.time}} -->
						
							{{item.content}}
						
					
				
			
			
				
				
				
					
						发 送
					
				
			
		
	


	// 自家后端的接口,发送问题,返回ai答案获取接口
	import {
		getSign
	} from '@/api/aiChat/aiChat.js';
	// 安装fetch-event-source后引入,通过fetch-event-source获取流式答案数据
	import {
		fetchEventSource
	} from '@microsoft/fetch-event-source'
	
	export default {
		name: "onlineCustomer",
		components: {},
		computed: {},
		data() {
			return {
				userId: null,
				customerText: "",
				isShow: true,
				Sending: true,
				getHistoryId: "",
				info: [{
					type: "leftinfo",
					time: this.getTodayTime(),
					name: "robot",
					content: "你好,这里是智能匹配",
					question: [],
				}, ],
				timer: null,
				keyboardHeight: 0,
			};
		},
		created() {
			this.showTimer();
		},
		onLoad() {
			this.GetRequest();
		},
		mounted() {
			window.addEventListener('resize', this.handleResize);
		},
		beforeDestroy() {
			uni.offKeyboardHeightChange();
			window.removeEventListener('resize', this.handleResize);
		},
		watch: {
			keyboardHeight(newHeight) {
				this.onKeyboardShow(300);
				if (newHeight > 0) {
					// this.onKeyboardShow(230);
				} else {
					this.onKeyboardHide();
				}
			}
		},
		methods: {
			///换行符、加粗符更换为适配html
			formatContent(content) {
				// 处理换行符
				let formattedContent = content.replace(/\n/g, '
'); // 处理加粗 formattedContent = formattedContent.replace(/\*\*(.*?)\*\*/g, '$1'); return formattedContent; }, handleResize() { this.keyboardHeight = 0; // 重置键盘高度 }, onKeyboardShow(height) { this.$nextTick(() => { const content = document.getElementById('content'); content.style.paddingBottom = `${height}rpx`; content.scrollTop = content.scrollHeight; }); }, onKeyboardHide() { this.$nextTick(() => { const content = document.getElementById('content'); content.style.paddingBottom = '0px'; }); }, scrollToView() { this.$nextTick(() => { document.getElementById('text').scrollIntoView({ behavior: 'smooth', block: 'center' }); }); }, //获取历史数据 getHistory() { var getHistory = uni.getStorageSync(this.getHistoryId); if (!getHistory) { uni.showToast({ title: '暂无历史记录', icon: 'none', duration: 2000 }); return; } console.log('获取历史数据'); this.info = []; console.log(getHistory); var i = 0; for (i; i { var contentHeight = document.getElementById("content"); contentHeight.scrollTop = contentHeight.scrollHeight; }); } }, // 机器人回答消息 async appendRobotMsg(text) { clearTimeout(this.timer); this.showTimer(); text = text.trim(); // 获取ai答案接口 var data = { question: text } const answerUrl = await getSign(data) let obj2 = { type: "leftinfo", time: this.getTodayTime(), name: "robot", content: '正在输入中...', question: [], }; this.info.push(obj2); this.$nextTick(() => { //滚动聊天到底部 var contentHeight = document.getElementById("content"); contentHeight.scrollTop = contentHeight.scrollHeight; }); let abortController = new AbortController() // 存获取到的流式数据中要显示的内容 let answerArr = [] const that = this fetchEventSource(answerUrl, { method: 'post', headers: { Accept: 'text/event-stream', Authorization: 'Bearer ' // 智谱AI的key,后端提供 }, signal: abortController.signal, async onopen(response) { //建立连接的回调 console.log('建立连接的回调') }, onmessage(msg) { // console.log("流式数据", msg); //接收一次数据段时回调,因为是流式返回,所以这个回调会被调用多次 if (msg.event == 'add' && JSON.parse(msg.data).msg) { //进行连接正常的操作 try { const dataObj = JSON.parse(msg.data).msg // 存获取到的流式数据中要显示的内容 answerArr.push(dataObj) } catch (e) {} } }, onclose() { // 流式数据获取结束后的操作 // that.info[that.info.length - 1].content = answerArr.join('') // 将获取到的流式数据要显示的内容以类似打字的方式展示到聊天窗口中 let index = 0; let combinedString = ''; const intervalId = setInterval(() => { // 检查是否还有未处理的数组项 if (index { //滚动聊天到底部 var contentHeight = document.getElementById("content"); contentHeight.scrollTop = contentHeight.scrollHeight; }); index++; } else { // 答案都显示后,才能再次提问 that.Sending = true; // 如果所有项都已处理完毕,清除定时器 clearInterval(intervalId); } }, 200); that.$nextTick(() => { //滚动聊天到底部 var contentHeight = document.getElementById("content"); contentHeight.scrollTop = contentHeight.scrollHeight; }); }, onerror(err) { //连接出现异常回调 // 取消请求 throw err } }) }, saveChatRecord(newChatRecord) { // 获取当前存储的聊天记录列表,如果不存在则初始化为空数组 let chatRecords = uni.getStorageSync(this.getHistoryId); // 如果不存在,则初始化为空数组 if (!Array.isArray(chatRecords)) { chatRecords = []; } // 将新的聊天记录对象追加到聊天记录列表中 chatRecords.push(newChatRecord); // 将更新后的聊天记录列表保存回本地存储 uni.setStorageSync(this.getHistoryId, chatRecords); }, // 结束语 endMsg() { let happyEnding = { type: "leftinfo", time: this.getTodayTime(), content: "感谢您使用智能匹配,祝您生活愉快", question: [], }; this.info.push(happyEnding); this.$nextTick(() => { var contentHeight = document.getElementById("content"); contentHeight.scrollTop = contentHeight.scrollHeight; }); }, showTimer() { // this.timer = setTimeout(this.endMsg, 1000 * 180); }, getTodayTime() { // 获取当前时间 var day = new Date(); let seconds = day.getSeconds(); if (seconds
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码