因为女朋友的一句话,我把ChatGpt接入了微信

之前的操作一直是通过官方网址直接提问,奈何这样的方式对于网上冲浪的水平有一定要求。笔者的女朋友又是一个问题宝宝,经常看到她在百度上搜索各种答案却不得其解,抓耳挠腮的样子。便萌生了接入微信聊天,方便向ChatGpt提问的想法。

项目部署基于大佬的源码,源码地址

一、简易版(微信个人账号)

ChatGpt机器人的工作原理是微信扫码登陆后,当触发某些关键词时,通过API调用ChatGPT的接口进行回复。

准备工作

  1. 注册一个ChatGpt账号,教程参考:ChatGPT保姆级教程,一分钟学会使用ChatGPT!
  2. 创建完账号则前往 API管理页面 创建一个 API Key 并保存下来,后面项目配置中会用到。

开始部署

基础版很简单,可以参考源码地址中的README.md文档进行部署。

这里推荐使用Railway进行部署,注册一个railway账号后即可一键部署。

部署过程中需要填入一些配置变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# config.json文件内容示例
{
"open_ai_api_key": "YOUR API KEY", # 填入上面创建的 OpenAI API KEY
"model": "gpt-3.5-turbo", # 模型名称。当use_azure_chatgpt为true时,其名称为Azure上model deployment名称
"proxy": "127.0.0.1:7890", # 代理客户端的ip和端口
"single_chat_prefix": ["bot", "@bot"], # 私聊时文本需要包含该前缀才能触发机器人回复
"single_chat_reply_prefix": "[bot] ", # 私聊时自动回复的前缀,用于区分真人
"group_chat_prefix": ["@bot"], # 群聊时包含该前缀则会触发机器人回复
"group_name_white_list": ["ChatGPT测试群", "ChatGPT测试群2"], # 开启自动回复的群名称列表
"group_chat_in_one_session": ["ChatGPT测试群"], # 支持会话上下文共享的群名称
"image_create_prefix": ["画", "看", "找"], # 开启图片回复的前缀
"conversation_max_tokens": 1000, # 支持上下文记忆的最多字符数
"speech_recognition": false, # 是否开启语音识别
"group_speech_recognition": false, # 是否开启群组语音识别
"use_azure_chatgpt": false, # 是否使用Azure ChatGPT service代替openai ChatGPT service. 当设置为true时需要设置 open_ai_api_base,如 https://xxx.openai.azure.com/
"character_desc": "你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。", # 人格描述
# 订阅消息,公众号和企业微信channel中请填写,当被订阅时会自动回复,可使用特殊占位符。目前支持的占位符有{trigger_prefix},在程序中它会自动替换成bot的触发词。
"subscribe_msg": "感谢您的关注!\n这里是ChatGPT,可以自由对话。\n支持语音对话。\n支持图片输出,画字开头的消息将按要求创作图片。\n支持角色扮演和文字冒险等丰富插件。\n输入{trigger_prefix}#help 查看详细指令。"
}

最重要的就是open_ai_api_key,填入准备工作中的OpenAI API KEY。

其他的一些配置是触发机器人回复的前缀、开启自动回复的群聊名称等等。可以配置这些可根据实际使用需要修改配置。 我这里就是所有群聊都可以开启机器人:

image

配置完毕后直接进行部署,完成会生成一个二维码,通过微信扫描二维码登陆后(类似于网页版微信),即刻开启机器人回复。

image

私聊:

image

群聊:

image

至此,一个ChatGPT机器人就搭建完成了。

简易版存在的问题

  1. 因为微信机制的原因,微信扫码登陆会要求手机端必须在线,同时电脑端和网页端不可以同时登陆,所以日常工作需要电脑登陆微信的话会有不便,最好是单独准备一个备用机和备用微信。
  2. 这样就引发了另一个问题:经常掉线。经常登陆1-2天后,机器人就掉线了,且日志打印log out无其他异常信息。 个人猜测是因为微信网页端存在测活机制,如果一定时间内该微信账号没有活跃迹象,会强制登出。 需要重新部署服务后再次扫码登陆,有点影响使用体验。
  3. 个人微信登陆存在封号的风险(不过我使用过程中未收到帐号异常的提醒)

二、升级版(微信订阅号)

为了解决简易版的一系列问题,通过微信订阅号来实现。

实现原理:我们在关注公众号或订阅号的时候,经常发现我们输入某些关键词就会触发公众号的自动回复。这里的自动回复可以通过公众号配置,也可以通过服务器转发。即将用户的输入转发作为请求调用服务器的接口,将服务器接口的返回作为公众号的回复。

准备工作

  1. 一个拥有公网IP的服务器,或者本地启动服务后进行内网穿透,否则微信服务器无法将消息发送给我们的服务器。服务器的系统最好是ubuntu,不然会存在部分依赖无法安装的情况。
  2. 微信公众号,类型选择订阅号。
  3. 一个可以科学上网的订阅地址。

本人环境:

  • 系统版本: Ubuntu 22.04 LTS
  • python版本:python3.10
  • pip版本:pip 22.0.2

微信公众平台-基本配置

公众号注册完后后需要进行如下配置

image

  • appId:微信公众平台生成。
  • appSecret:需要自己手动在微信公众平台生成,并做好保存。
  • IP白名单:服务器的ip地址。
  • 服务器地址:http:///wx, 根据自己实际ip地址替换。
  • token:自定义。
  • EncodingAESKey:手动在微信公众平台生成(消息加密方式为密文时候用到)。

服务器部署

  1. 登陆服务器,克隆代码
Text
1
git clone https://github.com/zhayujie/chatgpt-on-wechat
  1. 安装依赖
1
2
3
4
5
6
# 进入项目目录
cd chatgpt-on-wechat/
# 安装核心依赖
pip3 install -r requirements.txt
# 安装其他依赖(也要安装)
pip3 install -r requirements-optional.txt
  1. 安装python的web框架web.py和wechatpy
Text
1
2
pip3 install web.py
pip3 install wechatpy
  1. 增加配置
    新建config.json文件,并加入下面配置,配置的相关内容根据自己的微信公众平台和服务器信息填写。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
"open_ai_api_key":"",
"channel_type":"wechatmp",
"wechatmp_token":"",
"wechatmp_port":8080,
"wechatmp_app_id":"",
"wechatmp_app_secret":"",
"wechatmp_aes_key":"",
"single_chat_prefix":[
""
],
"single_chat_reply_prefix":"",
"plugin_trigger_prefix":"&",
"model":"gpt-3.5-turbo",
"proxy":"127.0.0.1:7890",
"group_chat_prefix":[
"@bot"
],
"group_name_white_list":[
"ALL_GROUP"
],
"group_chat_in_one_session":[
"ALL_GROUP"
],
"image_create_prefix":[
"画",
"看",
"找"
],
"conversation_max_tokens":1000,
"speech_recognition":false,
"group_speech_recognition":false,
"use_azure_chatgpt":false,
"character_desc":"你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。",
"subscribe_msg":"感谢您的关注!\n这里是ChatGPT,可以自由对话。\n支持语音对话。\n支持图片输出,画字开头的消息将按要求创作图片。\n支持角色扮演和文字冒险等丰富插件。\n输入{trigger_prefix}#help 查看详细指令。"
}
  • open_ai_api_key:简易版中API Key
  • channel_type:wechatmp或wechatmp_service, wechatmp是个人主体的微信订阅号,目前存在回复时间限制,每天的图片和声音回复次数也有限制。而wechatmp_service需要通过微信认证,不存在这些限制。
  • wechatmp_token:微信公众平台的Token,这里填的需要和微信公众平台中填的一致,待会会有校验。
  • wechatmp_port:微信公众平台的端口,需要端口转发到80或4430。
  • wechatmp_app_id:微信公众平台的appID。
  • wechatmp_app_secret:微信公众平台的appsecret。
  • wechatmp_aes_key:微信公众平台的EncodingAESKey,加密模式需要。
  • plugin_trigger_prefix: 推荐设置,在手机微信客户端中,$%^等符号与中文连在一起时会自动显示一段较大的间隔,用户体验不好。请不要使用管理员指令前缀”#”,这会造成未知问题。
  1. 运行启动web服务器
    使用nohup命令在后台运行程序:
1
2
touch nohup.out                                   # 首次运行需要新建日志文件  
nohup python3 app.py & tail -f nohup.out # 在后台运行程序并通过日志输出二维码
  1. 端口转发
    服务启动的端口默认是8080端口,但是微信公众号的服务器配置只支持80/443端口,使用端口转发命令将80端口转发到8080端口。
Text
1
2
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables-restore < /etc/iptables/rules.v4

微信公众平台-服务器配置

  1. 提交服务器配置

image
提交服务器配置的时候会校验服务是否可用和token是否一致,服务不可用或者token不一样,会提示token验证失败。

image

  1. 启用服务器

启用服务器后,订阅号收到的消息将会被转发到服务器,可以在日志文件nohup.out中看到。

发送消息:

image

日志打印:

Text
1
2
3
4
[INFO][2023-05-15 16:41:03][chat_gpt_bot.py:49] - [CHATGPT] query=你好
[WARNING][2023-05-15 16:41:09][chat_gpt_bot.py:138] - [CHATGPT] APIConnectionError: Error communicating with OpenAI: HTTPSConnectionPool(host='api.openai.com', port=443): Max retries exceeded with url: /v1/chat/completions (Caused by ProxyError('Cannot connect to proxy.', NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000001E7F7DF39A0>: Failed to establish a new connection: [WinError 10061] 由于目标计算机积极拒绝,无法连接。')))
[INFO][2023-05-15 16:41:10][wechat_channel.py:187] - [WX] sendMsg=Reply(type=ERROR, content=[ERROR]
我连接不到你的网络), receiver=@86f21b179a0a03c26d1e6d93105790236ff5451d144f4c5a6f5ac0a6902d48a0

配置代理转发

细心的朋友会发现,在上一步中,微信公众号返回了错误,日志中也打印了目标服务器无法连接的错误。

这一步是因为我们的服务器不能直接连接openai的接口,需要配置代理进行转发。

  1. 下载项目
Text
1
2
3
4
# 到上一级目录
cd ..
# 下载项目
git clone https://github.com/wanhebin/clash-for-linux.git
  1. 修改订阅地址
Text
1
2
3
4
# 进入项目目录
cd clash-for-linux
# 修改配置
vim .env

将CLASH_URL改为订阅地址。
3. 启动程序

Text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 运行启动脚本
$ sudo bash start.sh

正在检测订阅地址...
Clash订阅地址可访问! [ OK ]

正在下载Clash配置文件...
配置文件config.yaml下载成功! [ OK ]

正在启动Clash服务...
服务启动成功! [ OK ]

Clash Dashboard 访问地址:http://<ip>:9090/ui
Secret:xxxxxxxxxxxxx

请执行以下命令加载环境变量: source /etc/profile.d/clash.sh

请执行以下命令开启系统代理: proxy_on

若要临时关闭系统代理,请执行: proxy_off
  1. 配置环境变量&开启代理
Text
1
2
$ source /etc/profile.d/clash.sh
$ proxy_on
  1. 检查
Text
1
2
3
4
5
6
7
8
9
10
11
# 检查服务端口
netstat -tln | grep -E '9090|789.'
tcp 0 0 127.0.0.1:9090 0.0.0.0:* LISTEN
tcp6 0 0 :::7890 :::* LISTEN
tcp6 0 0 :::7891 :::* LISTEN
tcp6 0 0 :::7892 :::* LISTEN

# 检查环境变量
env | grep -E 'http_proxy|https_proxy'
http_proxy=http://127.0.0.1:7890
https_proxy=http://127.0.0.1:7890

以上步鄹如果正常,说明服务clash程序启动成功。

  1. 再次进行订阅号消息测试

image
成功!