前段时间把ChatGPT接到了公众号的后台,最终效果大致就是给公众号发消息,等同于在GPT的网页上发消息,可以正常回复消息,且可以识别上下文。趁着端午节有时间,记录一下过程。
在微信公众号后台接入点东西,是一件麻烦且不稳定的事情,其实不单单是微信,整个腾讯系都如此,毕竟无风不起浪,腾讯四处招骂都是凭本事做到的。
之前我看过不少接入ChatGPT的公众号、小程序,但基本都没挺过头七,然后就搜不到了。网上见到有网友在问,说自己的号被封了,微信只给了一个条款链接,也不说到底违反了哪一条哪一款,客服也联系不上,提问公众号到底允不允许接入ChatGPT。
没有人可以说得清,微信的政策是一个已经上升到玄学高度的问题,所以我一直没有试一试的想法,上一秒还正常,下一秒可能号就没了。
直到我关注的一个ChatGPT问答的小程序,活生生坚挺了一个多月竟然还健在,仔细看了看,发现原来他还接入了腾讯审核,真相大白,真是机灵。所以我猜测,微信封的不是ChatGPT,而是里面的文字内容,原因在于国内互联网有些内容是不能提的。
1. 公众号的消息机制
微信开发者文档关于消息机制的介绍
公众号后台把消息分为2种,一种是主动消息,一种是被动消息。
首先一个前提是,在公众号后台配置一个URL后,这个URL就会收到用户发送的所有消息,以及相关事件,比如关注、菜单栏点击,等。
当用户给公众号发一条消息后,后台收到这条消息,并回复一条消息,这种消息叫做被动消息。即非主动发送,是对用户发过来的消息的被动回复,这种消息要求实时性。
如果回复完之后,还想给用户发消息怎么办?这个时候就需要发送主动消息,公众号后台管这种叫做客服消息。一般使用场景是,用户咨询了一个问题,对于这个问题无法立即给出回答,需要经过一段时间处理后,才可以给用户回复他提问的答案,这种消息不要求实时性。
被动消息
URL在收到微信服务器发来的带着用户消息的请求后,需要在5秒以内给出response,如果超时,微信的服务器会发起重试,最多重试3次。换句话说,用户发送一条消息,开发者最多有15秒的处理时间,如果超过15秒还没有给出response,那么用户那边就会看到一个提示:
该公众号暂时无法提供服务,请稍后再试
主动消息(客服消息)
这个类型的消息有限制,48小时内只允许发5次,看这个频率就知道,不适合这种问答场景。同时,它的设计是按照客服体系结构的,需要提前创建客服,URL收到消息后需要将这个消息分配给某个客服,然后这个客服需要在48小时内给出回复。
2. 消息交互方式选择
问ChatGPT一个问题,它回复需要的时间是不稳定的,具体影响因素有网络、问题本身、上下文长度、回答的长度等,快的时候一两秒就能回来,慢的时候需要十几秒,甚至几十秒。按理说,这种时间跨度,使用不限时的客服消息是比较好的选择,但是无奈于它的条数限制,所以只能选择被动消息的方式。
对于15秒仍无法给出答案的问题,这种情况的一般处理方式是,给用户回复一个提示,引导他再发一条消息,这样一来又有了15秒的时间。虽然体验上差了一点,但是起码保证了基本的可用性。故终决定使用此方式。
3. 服务选择
关于服务器,当下有2种选择,一种是长期跑着一台机器来提供服务,即EC2,另一种是按需使用,即FaaS。量小的话就选FaaS,省钱,量大的话就选EC2,也是为了省钱。
我用的是阿里云,新用户送了一些计算资源、带宽资源和存储资源,有效期3个月,前期就不用花钱了。
服务器URL直接用Function服务的调用URL,也没走API Gateway,因为阿里云没送,存储没用RDS,用的是OSS,也是因为阿里云送了免费的资源,那就先用着。
内容审核肯定是要接腾讯的了,文本审核按条收费,一万条收费22块钱,这大概是唯一的必要花费了。
对于ChatGPT,早年间我注册过一个账号,那个时候还不像现在这么艰难,注册很容易。里面送了18块钱的额度,6月1号过期,一直在用,按理说可以用到过期。但五月份的时候用着用着账号就被封了,突然就没得用了,于是就赶紧从众多的二道贩子中选了一个用户稍微多点的,价格比官方贵了20%左右,当然贵也很正常,很好理解,人家就是赚差价的。虽然没了账号的困扰,但是随之而来的是安全性,自己的所有数据都会经过他们的手,即便他们嘴上说着不会存储,但心里也不踏实,所以有办法的话还是要自己搞个官方账号。
所以,所有需要接入的服务如下:
- 阿里云的Function服务
- 阿里云的Log日志服务
- 阿里云的OSS对象存储服务
- 腾讯云的内容审核服务
- 第三方的ChatGPT服务
4. 阿里云Function服务使用
首先需要的就是接通阿里云的函数服务,可以做到向函数URL发送一个request,代码中可以正确接收、处理,并返回response。
语言和框架
函数服务可以选择不同语言的不同版本,鉴于ChatGPT用的Python,所以我选了Python,3.9版本。服务框架有2种选择,一个是普通的事件模式,http请求的所有参数,包括请求参数、请求头、请求体等,会被包装成一个event,我们在代码里要做的就是要处理一个一个不同类型的事件;另一个则是Flask框架,这个本就是一个轻型的http服务框架,可以处理http请求。我选的是后者。
部署
关于部署,最直接的方式是把本地代码打包,然后从管理后台上传,再部署。但最简单快速的便是一键部署,我试了常用serverless框架来部署,但是失败了,原因就是反复从文档中查找失败原因时,发现有一行字写着serverless只支持Amazon,不支持阿里云。
最终选择了通过GitHub的方式,将部署和仓库的分支绑定,向分支上提交内容则会触发自动部署操作,代码是交出去了,用几分安全性换取了几分便捷性。
在管理后台上创建函数服务时,它会自动生成一套模版代码,等它部署完之后,访问函数服务的URL就可以看到示例页面。把仓库clone到本地,在此基础上稍微修改一下部署配置就可以用了。
关于配置项不知道写什么值,这个可以逆向操作一下,在后台可视化的网页上修改配置,增加服务或者修改服务,比如给函数增加一个Log服务,完成之后右上角有一个导出配置文件,再将导出的配置整合到代码里的配置文件即可。
这里就不举例了,内容太多,文末会附一个脱敏的代码仓库,需要的话可以参考一下。
5. 阿里云的OSS对象存储服务
对象存储,就可以把它当作文件存储服务使用,这个服务最近在搞推广,可能是新产品,或者新升级的产品。需要先创建一个存储桶,用来存放文件,里面的文件可以按目录文集存储,比如创建个文件夹,按类别存储文件。其实实际上OSS没有文件的存在的,所有的文件都是直接存储在存储桶里,只不过是给文件增加了路径的属性,这是关于OSS的内部实现,我们不需要关心,它能用就行。
1 | ossMountConfig: |
如上这个配置,则是创建了一个名字是wechat-bucket的存储桶,把桶的/目录挂载到了服务器的/home/app下。这个其实就是一个路径映射,比如桶里有2个文件,一个是名字的文本文件,一个在users目录下有个头像图片,
1 | wechat-bucket/name.txt |
当在代码里读取这两个文件时,对应的路径就是:
1 | /home/app/name.txt |
6. 腾讯云的内容审核服务
接入文本审核,我就打心底里有种感觉,照着腾讯的文档接腾讯的服务,这是一件折磨人的事。原因在于版本多,且不统一。
比如请求的Authorization的值的计算,因为每个接口都要用,所以它在通用文档里写了一份;因为文本审核、图片审核、视频审核等所有的审核服务都要用到,所以它又在审核部分的通用部分写了一份;因为文本审核自己用到了,然后它又在文本审核里单独写了一份;每个地方的版本都有差别,而且每个地方都在互相引用,这个中间值让参考这个链接里的方式,这个中间值又要参考那个链接;甚至它还说,请求可以有这个签名的值,也可以不带这个值;还有在线计算工具,还有示例代码,每个地方都是不一样的版本。它甚至还给了python版本的SDK,照着文档去调用SDK时,SDK报错,说不支持这种审核方式。
想说的太多太多了。最终的结果就是,但是接入这个文本审核的时间,远远超出了做其他事加在一起的总时间。调试阿里云的函数服务配置时,我还觉得阿里云的文档写的不好,等到接这个腾讯云的时候,我又觉得有点错怪阿里云了,起码它没让我反复反复试错文档的错误、排除文档中的不可行性。
其实要做的事再简单不过了,发起一个request,请求体就是需要审核的文本,接收一个response,获取审核的结果,通过或者不通过,仅此而已。
7. ChatGPT
相比其他,这算是最好接入的了,有SDK,有文档,照着文档操作,可以一步到位,没有过多可说的。
官方文档地址
它有2种常用的模式,一个叫做Completions,还有一个叫做Chat。Completions适应的场景就是一问一答,然后结束,没有上下文。而Chat则可以连续对话,上下文内容会影响它的回答。
因为需要满足理解上下文的需求,我这里使用的是Chat。
其实相比于Completions,Chat也没有多神奇,它不过是每次请求时,都带着所有的聊天记录,包括你问过的问题,以及它给出的答案。这就意味着,对话的回合数越多,请求体就会越大,而ChatGPT是按照字数收费的,这个字数包括问题的字数和回答的字数。
所以为了避免问完一个问题房子就没了的困境,我限制里每个提问里携带的历史记录,只带3组历史问答。而实际上,也没有必要带上所有的历史记录,一般只有最近的几个回答有实际的参考价值。
附录
微信测试号
微信公众号有不同类别,不同种类的号有不同的限制,有些接口只有认证过的号才能调用,认证一次要好几百,而且不同认证之间不通用,也就是说这个服务需要这个认证,那个服务需要那个认证,这个时候,微信就贴心的提供了测试号,这个账号可调用所有API,可使用所有服务,且没有限制,每个微信号可注册一个。
点击进入微信测试号
ChatGPT账号
ChatGPT的网页版和API接口虽然使用的是同一个账号,但其实这是两个独立的东西,所以这两个的Plus也是相互独立不通用的,充值网页版的plus则只能使用网页版的GPT4,要想API也用GPT4,就要想办法给账号绑定个信用卡,或者GooglePay之类的支付方式,这种方式叫做Pay As You Go,OpenAI的风控系统一直在不断调整,所以支付方式也需要随机应变。
还有一点,充值过的账号比没充值的更容易被封号,就像我的账号一直用了快半年了都相安无事,结果自打在淘宝上买了个网页版的plus之后,用了一个礼拜号就没了。
参考代码
https://github.com/oynix/wechat_gpt