ChatGPT简介与Q群机器人部署教程

First Post:

Last Update:

Word Count:
4.3k

Read Time:
18 min

最近OpenAi推出的ChatGPT火出NLP圈子,看到不少人说强人工智能已经出现,于是赶紧来体验感受一下。
该项目计划长期进行维护更新,欢迎star:https://github.com/zstar1003/Qbot

ChatGPT简介

ChatGPT是一个基于GPT-3(通用语言模型)的聊天机器人。它的目的是能够通过自然语言交流与用户进行对话。它能够理解用户的输入,并根据用户的话语生成相应的回复。

这种技术的出现,标志着人工智能在自然语言处理方面取得了新的突破。GPT-3是目前世界上最大规模的语言模型,它被训练在数百万个文本文件上,因此具有非常强大的语言理解能力。通过在GPT-3的基础上构建ChatGPT,我们可以获得一个能够与人进行自然语言对话的机器人,它能够与人类的对话方式非常相似。

ChatGPT的优势在于它能够进行流畅的对话,并能够根据用户的输入自动生成合适的回复。它能够理解语境,因此可以提供更准确、更有帮助的回复。此外,它还具有语言表达能力,可以使用正确的语法和语言风格进行对话。


实际上,上面三段文字完全由ChatGPT自己进行生成,如果你没察觉到异常,说明它已经通过了“图灵测试”。

在这里插入图片描述

目前,ChatGPT没有开源,只能通过OpenAi提供的测试界面调试,

ChatGPT官网:https://chat.openai.com/chat
注:2022-12-12 OpenAi增加了5秒的cloudflare并且大幅缩短了token的存活时间(原24小时缩短为2小时),导致目前国内的一些镜像站均无法使用。

ChatGPT原理

目前ChatGPT没有相关的论文和开源代码,具OpenAi官方所述,ChatGPT是在GPT3.5架构的基础上加入了RLHF(Reinforcement Learning from Human Feedback,人类反馈强化学习)。

在这里插入图片描述

ChatGPT采用了InstructGPT的框架,InstructGPT的论文:https://arxiv.org/pdf/2203.02155.pdf

整体训练过程分成三个过程:监督学习、训练奖励模型、引入强化学习迭代模型。

在这里插入图片描述

ChatGPT部署

1.注册账号

首先需要注册OpenAi的账号,账号注册使用自己的邮箱,境内手机号验证无法通过,可以使用别的接码平台。
这里使用的是sms(https://sms-activate.org/cn/cashBack),具体操作步骤很多博文都有提到,不做赘述。

2.获取界面信息

进入到会话界面后,按F12打开开发者工具,在此处提取并记录session_token

在这里插入图片描述

同样的位置提取并记录cf_clearance

在这里插入图片描述

最后,还需要提取并记录user-agent,这里随便找一个数据包都能够找到这个值

在这里插入图片描述

3.调用测试

ChatGPT官方有提供用于调用的API,不过试用次数很少,后续使用价格昂贵。
官方API文档:https://beta.openai.com/docs/api-reference/completions/create?lang=python

调用需要设置自己的密钥:https://beta.openai.com/account/api-keys

在Github上,有很多开源的项目提供了很多非官方的调用库,我对于Python最为熟悉,因此使用了这个库https://github.com/acheong08/ChatGPT

安装方式:

1
pip3 install revChatGPT --upgrade

安装完之后,通过下面的程序进行测试:

1
2
3
4
5
6
7
8
9
10
11
12
from revChatGPT.revChatGPT import Chatbot

config = {
"session_token": "上一步的session_token",
"cf_clearance": "上一步的cf_clearance",
"user_agent": "上一步的user_agent"
}

# 创建ChatGPT实例
chatbot = Chatbot(config, conversation_id=None, debug=True)
message = chatbot.get_chat_response('你好', output="text")
print(message['message'])

这里的参数修改为上一步获取到的参数。

如果使用正常,会输出如下结果:

在这里插入图片描述

4.QQ机器人搭建

首先得有个小号,用于搭建机器人。
其次需要选择QQ机器人的框架,目前Github上也有很多选择,我这里使用go-cqhttp这个框架。

该框架支持windows和linux,我在本机上进行部署,因此选择了64位windows版本。
下载链接:https://github.com/Mrs4s/go-cqhttp/releases/download/v1.0.0-rc3/go-cqhttp_windows_amd64.exe

双击运行之后,选择3.正向代理,之后会产生一系列文件。

配置文件config.yml修改内容如下:

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# go-cqhttp 默认配置文件

account: # 账号相关
uin: QQ小号 # QQ账号
password: '' # QQ密码
encrypt: false # 是否开启密码加密
status: 0 # 在线状态 请参考 https://docs.go-cqhttp.org/guide/config.html#在线状态
relogin: # 重连设置
delay: 3 # 首次重连延迟, 单位秒
interval: 3 # 重连间隔
max-times: 0 # 最大重连次数, 0为无限制

# 是否使用服务器下发的新地址进行重连
# 注意, 此设置可能导致在海外服务器上连接情况更差
use-sso-address: true
# 是否允许发送临时会话消息
allow-temp-session: false

heartbeat:
# 心跳频率, 单位秒
# -1 为关闭心跳
interval: -1

message:
# 上报数据类型
# 可选: string,array
post-format: string
# 是否忽略无效的CQ码, 如果为假将原样发送
ignore-invalid-cqcode: false
# 是否强制分片发送消息
# 分片发送将会带来更快的速度
# 但是兼容性会有些问题
force-fragment: false
# 是否将url分片发送
fix-url: false
# 下载图片等请求网络代理
proxy-rewrite: ''
# 是否上报自身消息
report-self-message: false
# 移除服务端的Reply附带的At
remove-reply-at: false
# 为Reply附加更多信息
extra-reply-data: false
# 跳过 Mime 扫描, 忽略错误数据
skip-mime-scan: false

output:
# 日志等级 trace,debug,info,warn,error
log-level: warn
# 日志时效 单位天. 超过这个时间之前的日志将会被自动删除. 设置为 0 表示永久保留.
log-aging: 15
# 是否在每次启动时强制创建全新的文件储存日志. 为 false 的情况下将会在上次启动时创建的日志文件续写
log-force-new: true
# 是否启用日志颜色
log-colorful: true
# 是否启用 DEBUG
debug: false # 开启调试模式

# 默认中间件锚点
default-middlewares: &default
# 访问密钥, 强烈推荐在公网的服务器设置
access-token: ''
# 事件过滤器文件目录
filter: ''
# API限速设置
# 该设置为全局生效
# 原 cqhttp 虽然启用了 rate_limit 后缀, 但是基本没插件适配
# 目前该限速设置为令牌桶算法, 请参考:
# https://baike.baidu.com/item/%E4%BB%A4%E7%89%8C%E6%A1%B6%E7%AE%97%E6%B3%95/6597000?fr=aladdin
rate-limit:
enabled: false # 是否启用限速
frequency: 1 # 令牌回复频率, 单位秒
bucket: 1 # 令牌桶大小

database: # 数据库相关设置
leveldb:
# 是否启用内置leveldb数据库
# 启用将会增加10-20MB的内存占用和一定的磁盘空间
# 关闭将无法使用 撤回 回复 get_msg 等上下文相关功能
enable: true

# 媒体文件缓存, 删除此项则使用缓存文件(旧版行为)
cache:
image: data/image.db
video: data/video.db

# 连接服务列表
servers:
# 添加方式,同一连接方式可添加多个,具体配置说明请查看文档
#- http: # http 通信
#- ws: # 正向 Websocket
#- ws-reverse: # 反向 Websocket
#- pprof: #性能分析服务器

- http: # HTTP 通信设置
address: 0.0.0.0:8700 # HTTP监听地址
timeout: 5 # 反向 HTTP 超时时间, 单位秒,<5 时将被忽略
long-polling: # 长轮询拓展
enabled: false # 是否开启
max-queue-size: 2000 # 消息队列大小,0 表示不限制队列大小,谨慎使用
middlewares:
<<: *default # 引用默认中间件
post: # 反向HTTP POST地址列表
#- url: '' # 地址
# secret: '' # 密钥
# max-retries: 3 # 最大重试,0 时禁用
# retries-interval: 1500 # 重试时间,单位毫秒,0 时立即
- url: http://127.0.0.1:7777/ # 地址
secret: '' # 密钥
max-retries: 0 # 最大重试,0 时禁用
retries-interval: 1000 # 重试时间,单位毫秒,0 时立即

其中,QQ账号替换为自己的小号。

设置完后,点击go-cqhttp.bat,弹出二维码进行扫码登录即可。

5.后端逻辑

在上一步中,设置了QQ机器人监听本机7777这个端口用来发送信息,8700这个端口用来接收信息。这一步需要采用一个后端框架来处理和发送信息。这里参考[2]的提供的方案,采用轻量化的Flask作为后端框架。

首先需要安装环境依赖,新建requirements.txt,输入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
certifi==2022.12.7
charset-normalizer==2.1.1
click==8.1.3
Flask==2.2.2
idna==3.4
importlib-metadata==5.1.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.1
OpenAIAuth==0.0.3.1
PyMySQL==1.0.2
requests==2.28.1
tls-client==0.1.5
urllib3==1.26.13
Werkzeug==2.2.2
zipp==3.11.0

在python环境中安装上述依赖:

1
pip install -r requirements.txt

安装后,编写后端程序

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import json
import requests
from flask import request, Flask
from revChatGPT.revChatGPT import Chatbot

cqhttp_url = "http://localhost:8700" # CQ-http地址
qq_no = "自己的QQ号" # 机器人QQ号,记得修改
config = {
"session_token": "上一步的session_token",
"cf_clearance": "上一步的cf_clearance",
"user_agent": "上一步的user_agent"
}
# 创建一个服务,把当前这个python文件当做一个服务
server = Flask(__name__)
# 创建ChatGPT实例
chatbot = Chatbot(config, conversation_id=None)

# 与ChatGPT交互的方法
def chat(msg):
try:
message = chatbot.get_chat_response(msg)['message']
# 下面这行代码是获取对话id,如果你需要的话,id就是这么获取的
# chatbot.conversation_id
print("ChatGPT返回内容: ")
print(message)
return message
except Exception as error:
return str('别问了,我得休息一下了')

# 测试接口,可以用来测试与ChatGPT的交互是否正常,用来排查问题
@server.route('/chat', methods=['post'])
def chatapi():
requestJson = request.get_data()
if requestJson is None or requestJson == "" or requestJson == {}:
resu = {'code': 1, 'msg': '请求内容不能为空'}
return json.dumps(resu, ensure_ascii=False)
data = json.loads(requestJson)
print(data)
try:
msg = chat(data['msg'])
except Exception as error:
print("接口报错")
resu = {'code': 1, 'msg': '请求异常: ' + str(error)}
return json.dumps(resu, ensure_ascii=False)
else:
resu = {'code': 0, 'data': msg}
return json.dumps(resu, ensure_ascii=False)


# 测试接口,可以测试本代码是否正常启动
@server.route('/', methods=["GET"])
def index():
return f"你好,QQ机器人逻辑处理端已启动<br/>"


# qq消息上报接口,qq机器人监听到的消息内容将被上报到这里
@server.route('/', methods=["POST"])
def get_message():
if request.get_json().get('message_type') == 'private': # 如果是私聊信息
uid = request.get_json().get('sender').get('user_id') # 获取信息发送者的 QQ号码
message = request.get_json().get('raw_message') # 获取原始信息
sender = request.get_json().get('sender') # 消息发送者的资料
print("收到私聊消息:")
print(message)
# 下面你可以执行更多逻辑,这里只演示与ChatGPT对话
msg_text = chat(message) # 将消息转发给ChatGPT处理
send_private_message(uid, msg_text) # 将消息返回的内容发送给用户
if request.get_json().get('message_type') == 'group': # 如果是群消息
gid = request.get_json().get('group_id') # 群号
uid = request.get_json().get('sender').get('user_id') # 发言者的qq号
message = request.get_json().get('raw_message') # 获取原始信息
# 判断当被@时才回答
if str("[CQ:at,qq=%s]"%qq_no) in message:
sender = request.get_json().get('sender')
print("收到群聊消息:")
print(message)
# 下面你可以执行更多逻辑,这里只演示与ChatGPT对话
msg_text = chat(message) # 将消息转发给ChatGPT处理
msg_text = str('[CQ:at,qq=%s]\n'%uid) + str(msg_text) # @发言人
send_group_message(gid, msg_text) # 将消息转发到群里
if request.get_json().get('post_type') == 'request': # 收到请求消息
print("收到请求消息")
request_type = request.get_json().get('request_type') # group
uid = request.get_json().get('user_id')
flag = request.get_json().get('flag')
comment = request.get_json().get('comment')
if request_type == "friend":
print("收到加好友申请")
print("QQ:", uid)
print("验证信息", comment)
# false拒绝,你可以自己写逻辑判断是否通过
set_friend_add_request(flag, "false")
if request_type == "group":
print("收到群请求")
sub_type = request.get_json().get('sub_type') # 两种,一种的加群(当机器人为管理员的情况下),一种是邀请入群
gid = request.get_json().get('group_id')
if sub_type == "add":
# 如果机器人是管理员,会收到这种请求,请自行处理
print("收到加群申请,不进行处理")
elif sub_type == "invite":
print("收到邀请入群申请")
print("群号:", gid)
# false拒绝,你可以自己写逻辑判断是否通过
set_group_invite_request(flag, "false")
return "ok"


# 发送私聊消息方法 uid为qq号,message为消息内容
def send_private_message(uid, message):
try:
res = requests.post(url=cqhttp_url + "/send_private_msg",
params={'user_id': int(uid), 'message': message}).json()
if res["status"] == "ok":
print("私聊消息发送成功")
else:
print(res)
print("私聊消息发送失败,错误信息:" + str(res['wording']))

except:
print("私聊消息发送失败")


# 发送群消息方法
def send_group_message(gid, message):
try:
res = requests.post(url=cqhttp_url + "/send_group_msg",
params={'group_id': int(gid), 'message': message}).json()
if res["status"] == "ok":
print("群消息发送成功")
else:
print("群消息发送失败,错误信息:" + str(res['wording']))
except:
print("群消息发送失败")


# 处理好友请求
def set_friend_add_request(flag, approve):
try:
requests.post(url=cqhttp_url + "/set_friend_add_request", params={'flag': flag, 'approve': approve})
print("处理好友申请成功")
except:
print("处理好友申请失败")


# 处理邀请加群请求
def set_group_invite_request(flag, approve):
try:
requests.post(url=cqhttp_url + "/set_group_add_request",
params={'flag': flag, 'sub_type': 'invite', 'approve': approve})
print("处理群申请成功")
except:
print("处理群申请失败")


if __name__ == '__main__':
server.run(port=7777, host='0.0.0.0')

这里的QQ号,config信息替换为自己的内容。

运行之后,就部署完成了。

ChatGPT评价

回到开头的问题,ChatGPT究竟算不算强人工智能?

以往NLP中的模型往往只能处理文本分类、文本续写、文本风格迁移等单一任务,而ChatGPT却能够处理多任务,的确是一大突破。然而,在测试过程中,它仍有一些问题:

  • 使用速度慢
    使用速度慢一方面是由于官方服务器同时段并发量大,另一方面是GPT类的模型是一个字一个字的输出,比如在官网上看到的是一个字一个字吐出来,而不是一整句话。如果插入到QQ机器人回复中,需要等待其将所有内容输出完再一并发送。内容越多,等待时间越久。
  • 太过“自信”
    ChatGPT很像一本百科全书,对于未知的东西,它仍然会“习惯性”地去做解释,甚至,它很容易被一些关键词所误导。比如,下图中群友对它进行的测试:

在这里插入图片描述

  • 无法获取最新信息
    ChatGPT是通过2021年以前的数据训练而来的,因此它无法获取最新信息,这让它无法取代搜索引擎。
  • 易被催眠
    最后这点,不多做解释,在群友的催眠下,它被成功洗脑了。。

在这里插入图片描述

TODD

后续计划在此框架下开发更多内容:

  • config自动设置
    目前官方界面的config两小时会失活,后续会想办法自动进行获取设置
  • 加入其它功能
    可能考虑添加Ai绘画等功能

后记

— 2023-02-12更

一段时间没关注ChatGPT了,没想到OpenAi和微软合作之后,又掀起了第二波热潮。
于是重新在GitHub上浏览最新消息,发现本已归档的ChatGPT逆向工程项目又开始更新,作者采用了代理池的方式,在此突破了官方的地区的封锁。

于是更新了一下:

1
pip3 install revChatGPT --upgrade

注:该版本需要的谷歌浏览器内核版本需在110以上,使用前需进行更新。

在这里插入图片描述

下面是一个新版的调用示例:

1
2
3
4
5
6
7
8
9
from revChatGPT.Unofficial import Chatbot

chatbot = Chatbot({
"email": "自己的账号",
"password": "自己的密码"
}, conversation_id=None, parent_id=None) # You can start a custom conversation

response = chatbot.ask("你好", conversation_id=None, parent_id=None) # You can specify custom conversation and parent ids. Otherwise it uses the saved conversation (yes. conversations are automatically saved)
print(response)

经实测发现,如果一分钟收到3个请求以上就会被限制一定时间,响应速度也不及GPT3的Api,不过优势在于免费,不限制输入长度,且有上下文记忆(又可以催眠了😄)

— 2023-02-16更

revChatGPT上面的Unofficial版本在第二天的更新中变成了V2,不过仅过了一天,原作者的代理服务器遭到了OpenAi的攻击,导致V2版本直接失效。
作者又紧急升级了V1版本,并绕过了Cloudfare检测,现在无需启动浏览器也能够正常运行。

调用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from revChatGPT.V1 import Chatbot

chatbot = Chatbot(config={
"email": "自己的账号",
"password": "自己的密码"
})

for data in chatbot.ask(
'你好',
conversation_id=chatbot.config.get("conversation"),
parent_id=chatbot.config.get("parent_id"),
):
result = data["message"]

print(result)

后面更新情况不打算在更新了,后续的变化将直接写入仓库中,敬请关注(star)Qbot仓库,地址在文首。

参考

[1]ChatGPT是怎样被训练出来的?https://www.bilibili.com/video/BV1BG4y137SH/
[2]使用Python对接OpenAi APi 实现智能QQ机器人 https://lucent.blog/?p=99