在微信小程序中如何支持使用流模式(stream),打造ChatGPT实时回复机器人,最详细讲解。

这篇具有很好参考价值的文章主要介绍了在微信小程序中如何支持使用流模式(stream),打造ChatGPT实时回复机器人,最详细讲解。。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

有开发过ChatGPT相关应用的都知道,小程序是不支持流式请求的,目前市面上大多数开发者的解决方案都是使用websocket来解决。

还有一部分开发者是小程序嵌套网页解决这个问题,前者对于我们软件销售型的团队来说,交付会很麻烦,而且问题也会很多,而后者主要是体验不怎么好,而且需要设置网页授权域名。

作为ChatGPT最早期的开发者,我们开发的ChatGPT分销版占据了市面上60%左右的市场,和下面图片相似的都是我们的ChatGPT分销版。

在微信小程序中如何支持使用流模式(stream),打造ChatGPT实时回复机器人,最详细讲解。

 在开发这个项目之前,我们开源了这个产品的前端模板,现在市面上很多雷同的产品都是基于我们的模板进行开发的,或者是借鉴开发的。

有客户运营我们的产品,目前已经累计200w+的充值金额,净利润预估至少100w+,我们的产品质量源自于这些客户的数据支撑。

我们的后端使用ThinkPHP5.0进行开发,Saas架构,界面看上去很大气,如下图所示。

在微信小程序中如何支持使用流模式(stream),打造ChatGPT实时回复机器人,最详细讲解。

 颜值绝对秒杀市面上的所有ChatGPT应用,当然我们的定价和服务也是相当超值的。

废话不多说,接下来我来详细介绍下我是怎么实现微信小程序的流式请求的。

一、设置请求头

我的微信小程序和网页H5都是用的同一个接口,而微信小程序不支持stream的方式,只能使用分段传输的方式。

所以在这一步你需要做一个接口的兼容,我是传一个参数代表是微信小程序请求还是网页请求,从而设置不同的请求头。

网页H5的我就不给出header了,这里主要给出小程序的请求头,如下所示。

// 设置响应头信息
header('Access-Control-Allow-Credentials: true');
// 设置响应头信息
header('Transfer-Encoding: chunked');
header('Cache-Control: no-cache');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
header('Connection: keep-alive');
header('X-Accel-Buffering: no');

二,设置回复兼容

网页H5的流式请求我是直接返回的官方的响应数据,所以这里不能动之前的数据格式,在小程序请求这个接口时,需要单独返回对应的数据格式。

if ($is_wxapp) {
    echo "success: " . json_encode(['content' => $content]) . "\r\n";
}

结尾使用“\r\n”,并且当所有数据响应完成之后一定要输出0,如下图所示。

if ($is_wxapp) {
    echo "0\r\n\r\n";
    ob_flush();
    flush();
}

我这里为了兼容网页H5的流式请求,也是同样的加了判断之后输出的。

三,进入前端请求代码

以下是我完整的小程序请求方法,里面包含了我很多的业务逻辑,你可以根据你的业务进行修改,后面我会挑几个注意事项进行简述。

async onChatApplet() {
	let _this = this;
	let token = uni.getStorageSync('token');
	const url = "";
	const requestTask = uni.request({
		url: url,
		timeout: 15000,
		responseType: 'text',
		method: 'GET',
		enableChunked: true,
		data: {},
		success: response => {
			// console.log(response)
		},
		fail: error => {}
	})
	requestTask.onHeadersReceived(function(res) {
		// console.log(res.header);
	});
	requestTask.onChunkReceived(function(response) {
		const arrayBuffer = response.data;
		const uint8Array = new Uint8Array(arrayBuffer);
		let text = uni.arrayBufferToBase64(uint8Array)
		text = new Buffer(text, 'base64')
		text = text.toString('utf8');
		if (text.indexOf('error') > 0) {
			let error = text.replace("event: error\ndata: ", "").replace("\r\n", "")
			error = JSON.parse(error)
			let len = _this.question.length
			_this.disabled = false
			if (error.code == 0) {
				_this.$refs.uToast.show({
					type: 'error',
					message: error.msg
				})
				if (len > 0) {
					_this.question[len - 1].content = error.msg
				} else {
					_this.question[0].content = error.msg
				}
				return false;
			}
			if (in_array(error.code, [10001, 11000, 500, 404])) {
				let length1 = 0
				if (length1 > 0) {
					_this.question[length1 - 1].content = error.msg
				} else {
					_this.question[0].content = error.msg
				}
				_this.$refs.uToast.show({
					type: 'error',
					message: error.msg
				})
				return false;
			}
			switch (error.code) {
				case -1:
					_this.question.pop()
					uni.navigateTo({
						url: '/pages/user/passport/login'
					})
					break;
				case 101:
					_this.question.pop()
					_this.$refs.uToast.show({
						type: 'error',
						message: error.msg,
						complete() {
							uni.navigateTo({
								url: '/pages/user/recharge/index'
							})
						}
					})
					break;
				case 102:
					let length = _this.question.length
					if (length > 0) {
						_this.question[length - 1].content = error.msg
					} else {
						_this.question[0].content = error.msg
					}
					_this.$refs.uToast.show({
						type: 'error',
						message: error.msg
					})
					break;
				default:
					break;
			}
			return false;
		}
		if (text.indexOf('success') != -1) {
			let json = text.split('success: ');
			json.forEach(function(element) {
				if (element) {
					element = JSON.parse(element)
					let index = 0
					if (_this.question.length > 0) {
						index = _this.question.length - 1
					}
					_this.question[index].content += element.content;
					_this.$nextTick(() => {
						uni.pageScrollTo({
							scrollTop: 2000000,
							duration: 0
						});
					});
				}
			})
			return false;
		}
		let done = text.replace("\r\n", "")
		if (done == 0) {
			_this.disabled = false
		}
	})
}

注意事项:编码

const arrayBuffer = response.data;
const uint8Array = new Uint8Array(arrayBuffer);
let text = uni.arrayBufferToBase64(uint8Array)
text = new Buffer(text, 'base64')
text = text.toString('utf8');

我这个方式比较简单粗暴,我在网上看到有人使用了第三方库,但是我测试下来行不通,就使用了uni官方这个转成Base64,然后再进行转码。

以上就是整个小程序的流式响应回复所需要用到的技术,也是最直接有效的方法,如果你现在掌握这门技术,再加上ChatGPT目前的势头,我相信你也能做出一些事情。

好了,就这样,做一个小小的记录,后期如果有空,我会继续分享我在开发ChatGPT产品的其他思路。

个人公众号:程序员在囧途

欢迎大佬交流合作,交个朋友也行。文章来源地址https://www.toymoban.com/news/detail-455573.html

到了这里,关于在微信小程序中如何支持使用流模式(stream),打造ChatGPT实时回复机器人,最详细讲解。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【uni-app】只支持在微信小程序运行的 导入外部3d模型

    uniapp 导入3d模型,在微信小程序端运行。只支持在微信小程序端使用,若要支持 h5 和 APP端,可以查看这篇,点击这里 只导入了3d模型,未设置让模型动。 glb 格式 (1)首先文件 下载适配微信小程序的 three.js 地址:https://github.com/wechat-miniprogram/threejs-miniprogram (2)导入文件

    2023年04月08日
    浏览(36)
  • 在微信小程序中如何引入iconfont

    略 iconfont 指 https://www.iconfont.cn/。 通过 iconfont 可组建自己的图标库。 注册帐号 创建项目 添加图标 Font Family:默认为iconfont。当项目中已有iconfont名称的字体时,需要使用不同的名字。 略 将 iconfont.css 重命名为 iconfont20231007.wxss 将 iconfont20231007.wxss 文件复制到小程序的font目录

    2024年02月03日
    浏览(58)
  • 在微信小程序中如何改变默认打开的页面

    在微信小程序中,在我们编写页面的时候,可能会在重新渲染的时候导致页面跳转到默认打开的页面上,为了提升用户的一个体验,我们可以设置一些内容来修改小程序默认打开的页面,提升开发者的开发体验。 当我们打开一个微信小程序的时候,这里是普通编译 那么,我

    2024年02月03日
    浏览(55)
  • 如何在微信小程序中实现音视频通话

    微信小程序的音视频通话可以通过微信提供的实时音视频能力实现。这个能力包括了音视频采集、编码、传输和解码等多个环节,开发者只需要使用微信提供的 API 接口就可以轻松地实现音视频通话功能。 在具体实现上,开发者需要先在微信开放平台上注册并创建小程序,然

    2023年04月09日
    浏览(37)
  • 如何在微信小程序中加载自己的地图数据

    由于微信小程序无法进行DOM操作,导致像openlayers、leaflet这种常用的js库无法在微信小程序内使用,导致加载高德、百度、mapbox还有自定义的瓦片地图数据变得很困难。 目前,大多数情况下是使用以下三种方法实现加载自定义的瓦片数据。 1. 使用web-view 优势:可以使用丰富的

    2024年02月10日
    浏览(43)
  • 在微信小程序中如何配置腾讯位置服务并调用

    因为很多服务都已经被封装好了,所以我们只需要调用引入配置就行了。 下面进入正题,我们要先 先注册一个账号,然后点击控制台,进去以后找到左侧的应用管理,然后点击创建应用,创建完成以后点击添加key 添加好以后点编辑   然后填写好相应的信息  然后我们要下载

    2024年02月09日
    浏览(53)
  • uniapp项目如何运行在微信小程序模拟器上

    在HbuilderX中的小程序写完后自己一定要保存,否则会出不来效果 那么怎么让uniapp项目运行在微信小程序开发工具中呢 1 在hbuilderx中点击运行到小程序模拟器 2 然后在项目目录中会生成一个文件夹 在微信小程序开发软件中的工具安全设置打开端口 或者在微信小程序中导入项目

    2024年02月13日
    浏览(34)
  • 在微信小程序中怎么使用vant框架?

    Vant 是一个轻量、可定制的移动端组件库,于 2017 年开源。 目前 Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本,并由社区团队维护 React 版本和支付宝小程序版本。 Vant 是有赞前端团队开源的移动端组件库,于 2017 年开源,已持续维护 4 年时间。Vant 对内承载了有赞所

    2024年02月10日
    浏览(50)
  • 在微信小程序使用picker实现日期选择

    而且选择开始时间后,选择结束时间,能够选择的日期不能比开始日期还要早。要实现以上效果可这样写: 在wxml中写

    2024年02月16日
    浏览(46)
  • 在微信小程序中使用leafletwx加载自制手绘地图

    leafletwx是基于leaflet,使用微信原生组件开发的一套开源地图组件,目的是替换小程序内的原生map组件,项目开源地址:leatletwx。 加载自制手绘地图效果:  本示例开源地址在leafletwx的mymap页面。 可以使用gdal,安装成功后,使用命令 切分瓦片(使用gdal): gdal2tiles-l.py -l -p

    2024年01月24日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包