Compare commits
147 Commits
publish2.1
...
v3.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 43dc0f96ff | |||
| e02a82fa72 | |||
| 9f91b0c92b | |||
| d14d6364a3 | |||
| 15c8f0b6f7 | |||
| 9bca158174 | |||
| 45bb30692d | |||
| 5bf73caba7 | |||
| e5389f620a | |||
| 61fd52ff61 | |||
| 73c46bd812 | |||
| d8173122e0 | |||
| 1af6e77dd1 | |||
| ce476ca163 | |||
| 0a1df90a83 | |||
| 762f5ea30f | |||
| 06e7753797 | |||
| c5e1f8d3e9 | |||
| 221433725b | |||
| 28864cd066 | |||
| 854f70dc8b | |||
| 435b988223 | |||
| ecc119b296 | |||
| 209f3aa136 | |||
| 8935859934 | |||
| 6c77ec3534 | |||
| 291d3ebae8 | |||
| 5b97fd2e6f | |||
| 4de8c5ed7d | |||
| 09333d1604 | |||
| 60240ca9a1 | |||
| 3e45ec0a08 | |||
| 4aad04b31a | |||
| 99ff3f8d42 | |||
| f9a7a723aa | |||
| 7bb4ad648a | |||
| 7c3cb98cf8 | |||
| 0cc6bc0f1d | |||
| 4181d62b5c | |||
| 7a1c0b0821 | |||
| b74d32c2c8 | |||
| e320bb5ab8 | |||
| 076cfd3e97 | |||
| 515a937c07 | |||
| 2c5451120e | |||
| e6f6bee7ee | |||
| 1a137a8639 | |||
| c8f6d090cc | |||
| b7b7877dfc | |||
| 608bd0398e | |||
| 2541663b77 | |||
| 5d774f3d7b | |||
| 6ea1366e73 | |||
| 134a8e233a | |||
| 6ccfc674a5 | |||
| 37e9373561 | |||
| bfa8f137de | |||
| 66a85cddf5 | |||
| bf84e74490 | |||
| 3d8f96ef8a | |||
| 84c57a47ad | |||
| 5e101bb3c0 | |||
| 246fbd6337 | |||
| 9938e4392a | |||
| 10cda13213 | |||
| f3722b31d5 | |||
| 673a4e2c7f | |||
| 1d8fba05b6 | |||
| 7c06883975 | |||
| 6da12b7a67 | |||
| 0342d752e6 | |||
| a851e34c94 | |||
| ad8aed5724 | |||
| 75101bf270 | |||
| 43df7003d6 | |||
| 502703b749 | |||
| 8365f39f95 | |||
| aa5f8db59d | |||
| d2b60b72d9 | |||
| 14c36ceb52 | |||
| cdc3bdd769 | |||
| 48d0c2a8c8 | |||
| 6923979014 | |||
| 03239439c9 | |||
| da3381a887 | |||
| a1253cc241 | |||
| ffe10cc5c2 | |||
| 7093cf5ab8 | |||
| 979a0cdd2e | |||
| b495a11d1f | |||
| 8698e87e51 | |||
| 6d2f9e5ba8 | |||
| 0e24e107d6 | |||
| 888a4e89ab | |||
| 1a55684ae8 | |||
| 858712dcbc | |||
| ad4d068bbc | |||
| 0f5a2101b7 | |||
| 7bc9d8dc7b | |||
| 506a62e6e6 | |||
| 44e22087d8 | |||
| d88c06578d | |||
| 93bc12a89c | |||
| eedcb9b825 | |||
| b8fe50a196 | |||
| 10b1538118 | |||
| 09cfd18f6f | |||
| d01be66344 | |||
| c0e4d0595b | |||
| d403323a36 | |||
| 3092bbd210 | |||
| 9d2cd27705 | |||
| ec48b57358 | |||
| 54cdca01d3 | |||
| 4b35f7f8fd | |||
| 651ba7b3d6 | |||
| cd1390d449 | |||
| d478ff02b6 | |||
| 1da3a19ddd | |||
| db66cbfb9c | |||
| 51729f4a50 | |||
| d739abef60 | |||
| 2ecb3fc7cf | |||
| 69c576086e | |||
| a833812738 | |||
| b557bc1ec7 | |||
| 8ea7f42a1f | |||
| 9d553145ca | |||
| a38f3b9c28 | |||
| 9122b33fd0 | |||
| 91c6767522 | |||
| 5cf8df572a | |||
| 64bfac00a9 | |||
| 7407ac0ce1 | |||
| 0bb0493404 | |||
| 4366572675 | |||
| ffa3a0be3f | |||
| 4dc214b27e | |||
| 2baee48ff7 | |||
| 74ae9cbee0 | |||
| 1bfa325a6c | |||
| 5663c1d6b2 | |||
| 9a96456a77 | |||
| 9f741ef749 | |||
| dadaa10924 | |||
| 6b596dcb12 | |||
| 6d4d2bf84d |
@@ -0,0 +1,3 @@
|
||||
__pycache__
|
||||
botpy.log
|
||||
.vscode
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"python.analysis.typeCheckingMode": "basic"
|
||||
}
|
||||
@@ -1,25 +1,28 @@
|
||||
## ⭐体验
|
||||
扫码加入QQ频道
|
||||
|
||||

|
||||
使用手机QQ扫码加入QQ频道(频道名: GPT机器人 | 频道号: x42d56aki2)
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/37870767/230417115-9dd3c9d5-6b6b-4928-8fe3-82f559208aab.JPG" width="200"></img>
|
||||
|
||||
|
||||
**推荐Windows一键安装(版本更新更及时)!!**
|
||||
**请前往Release下载最新版本**
|
||||
|
||||
**详细部署教程链接**https://soulter.top/posts/qpdg.html
|
||||
|
||||
**详细部署教程链接**https://soulter.top/posts/qpdg.html
|
||||
|
||||
**详细部署教程链接**https://soulter.top/posts/qpdg.html
|
||||
|
||||
有任何问题请加频道反馈。
|
||||
|
||||
|
||||
**Windows用户推荐Windows一键安装,请前往Release下载最新版本(Beta)**
|
||||
有报错请先看issue,解决不了再在频道内反馈。
|
||||
|
||||
## ⭐功能:
|
||||
|
||||
近期新功能:
|
||||
- 支持一键切换语言模型(使用/bing /revgpt /gpt分别可以切换newbing、逆向ChatGPT、官方ChatGPT模型)
|
||||
- 热更新
|
||||
- 接入QQ,支持在QQ上和QQ频道上同时聊天!https://github.com/Soulter/QQChannelChatGPT/issues/82
|
||||
|
||||
支持的AI语言模型(请在`configs/config.yaml`下配置):
|
||||
- 逆向ChatGPT库
|
||||
- 官方ChatGPT AI
|
||||
- 文心一言(即将支持,链接https://github.com/Soulter/ERNIEBot 欢迎Star)
|
||||
- NewBing
|
||||
- Bard (即将支持)
|
||||
|
||||
部署QQ频道机器人教程链接:https://soulter.top/posts/qpdg.html
|
||||
|
||||
### 基本功能
|
||||
<details>
|
||||
<summary>✅ 回复符合上下文</summary>
|
||||
@@ -61,7 +64,7 @@
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>✅ 支持指令控制</summary>
|
||||
<summary>✅ 支持多种指令控制</summary>
|
||||
|
||||
- 详见下方`指令功能`
|
||||
|
||||
@@ -85,18 +88,24 @@
|
||||
- `/token`查看当前缓存的总token数
|
||||
- `/count` 查看统计
|
||||
- `/status` 查看chatGPT的配置
|
||||
- `/help` 查看帮助
|
||||
- `/key` 动态添加key
|
||||
- `/set` 人格设置面板
|
||||
|
||||
## 📰使用方法:
|
||||
|
||||
**详细部署教程链接**https://soulter.top/posts/qpdg.html
|
||||
|
||||
### 安装第三方库
|
||||
|
||||
使用Python的pip工具安装
|
||||
- `qq-botpy` (QQ频道官方Python SDK)
|
||||
- `openai` (OpenAI 库)
|
||||
- `openai` (OpenAI Python SDK)
|
||||
|
||||
```shell
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
> ⚠注意,由于qq-botpy需要运行在`Python 3.8+`的版本上,因此本项目也需要在此之上运行
|
||||
> ⚠注意,由于qq-botpy库需要运行在`Python 3.8+`的版本上,因此本项目也需要在此之上运行
|
||||
|
||||
### 配置
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
from aip import AipContentCensor
|
||||
|
||||
class BaiduJudge:
|
||||
def __init__(self, baidu_configs) -> None:
|
||||
if 'app_id' in baidu_configs and 'api_key' in baidu_configs and 'secret_key' in baidu_configs:
|
||||
self.app_id = str(baidu_configs['app_id'])
|
||||
self.api_key = baidu_configs['api_key']
|
||||
self.secret_key = baidu_configs['secret_key']
|
||||
self.client = AipContentCensor(self.app_id, self.api_key, self.secret_key)
|
||||
else:
|
||||
raise ValueError("Baidu configs error! 请填写百度内容审核服务相关配置!")
|
||||
def judge(self, text):
|
||||
res = self.client.textCensorUserDefined(text)
|
||||
if 'conclusionType' not in res:
|
||||
return False, "百度审核服务未知错误"
|
||||
if res['conclusionType'] == 1:
|
||||
return True, "合规"
|
||||
else:
|
||||
if 'data' not in res:
|
||||
return False, "百度审核服务未知错误"
|
||||
count = len(res['data'])
|
||||
info = f"百度审核服务发现 {count} 处违规:\n"
|
||||
for i in res['data']:
|
||||
info += f"{i['msg']};\n"
|
||||
info += "\n判断结果:"+res['conclusion']
|
||||
return False, info
|
||||
@@ -1,323 +0,0 @@
|
||||
2022-12-08 14:29:09,486 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 14:29:10,173 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 14:29:10,174 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 14:29:10,175 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 14:29:10,175 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 14:29:10,335 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 14:29:10,460 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 14:29:10,461 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 16:17:18,117 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 16:17:18,355 [ERROR] (http.py:73)_handle_response [botpy] 接口请求异常,请求连接: https://api.sgroup.qq.com/users/@me, 错误代码: 401, 返回内容: {'message': 'wrong bot token', 'code': 11242}, trace_id:829d8c60d296a3edcfac3d776dbd8b47
|
||||
2022-12-08 16:18:59,759 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 16:19:00,266 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 16:19:00,267 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 16:19:00,268 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 16:19:00,268 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 16:19:00,412 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 16:19:00,522 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 16:19:00,522 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 16:20:14,446 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 16:20:15,035 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 16:20:15,036 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 16:20:15,037 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 16:20:15,037 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 16:20:15,232 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 16:20:15,320 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 16:20:15,321 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 16:42:06,957 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 16:42:07,468 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 16:42:07,469 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 16:42:07,469 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 16:42:07,470 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 16:42:07,672 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 16:42:07,862 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 16:42:07,863 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 16:45:44,758 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 16:45:45,439 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 16:45:45,440 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 16:45:45,441 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 16:45:45,441 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 16:45:45,751 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 16:45:45,858 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 16:45:45,859 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 16:47:16,567 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 16:47:17,008 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 16:47:17,009 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 16:47:17,009 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 16:47:17,010 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 16:47:17,187 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 16:47:17,284 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 16:47:17,285 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 16:48:39,358 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 16:48:45,366 [WARNING] (http.py:188)request 请求超时,请求连接: https://api.sgroup.qq.com/gateway/bot
|
||||
2022-12-08 16:48:53,301 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 16:48:53,789 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 16:48:53,790 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 16:48:53,791 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 16:48:53,791 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 16:48:53,969 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 16:48:54,062 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 16:48:54,063 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 16:49:26,466 [ERROR] (http.py:73)_handle_response [botpy] 接口请求异常,请求连接: https://api.sgroup.qq.com/channels/7150805/messages, 错误代码: 403, 返回内容: {'code': 304003, 'message': 'url not allowed'}, trace_id:b201dd7b37649dcf47b82d54c58bc5dd
|
||||
2022-12-08 16:51:59,155 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 16:51:59,728 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 16:51:59,729 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 16:51:59,730 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 16:51:59,730 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 16:51:59,887 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 16:52:00,022 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 16:52:00,023 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 16:52:28,760 [ERROR] (http.py:73)_handle_response [botpy] 接口请求异常,请求连接: https://api.sgroup.qq.com/channels/7150805/messages, 错误代码: 403, 返回内容: {'code': 304003, 'message': 'url not allowed'}, trace_id:e62b072c9f0184f6bf7dd03a00fc0ef3
|
||||
2022-12-08 16:53:53,370 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 16:53:53,890 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 16:53:53,891 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 16:53:53,892 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 16:53:53,892 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 16:53:54,101 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 16:53:54,194 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 16:53:54,195 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 16:54:26,287 [ERROR] (http.py:73)_handle_response [botpy] 接口请求异常,请求连接: https://api.sgroup.qq.com/channels/7150805/messages, 错误代码: 501, 返回内容: None, trace_id:None
|
||||
2022-12-08 16:55:01,062 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 16:55:01,601 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 16:55:01,601 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 16:55:01,602 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 16:55:01,603 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 16:55:01,742 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 16:55:01,816 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 16:55:01,817 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 17:00:29,939 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 17:00:30,583 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 17:00:30,584 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 17:00:30,585 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 17:00:30,585 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 17:00:30,839 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 17:00:30,943 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 17:00:30,944 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 17:00:53,548 [ERROR] (http.py:73)_handle_response [botpy] 接口请求异常,请求连接: https://api.sgroup.qq.com/channels/7150658/messages, 错误代码: 403, 返回内容: {'code': 304003, 'message': 'url not allowed'}, trace_id:2ea547d78364cea60583ed450e589a17
|
||||
2022-12-08 17:10:31,405 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 17:10:32,081 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 17:10:32,082 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 17:10:32,083 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 17:10:32,083 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 17:10:32,342 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 17:10:32,449 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 17:10:32,450 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 17:13:47,495 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 17:13:47,993 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 17:13:47,994 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 17:13:47,995 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 17:13:47,995 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 17:13:48,198 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 17:13:48,300 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 17:13:48,302 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 17:16:31,326 [ERROR] (http.py:73)_handle_response [botpy] 接口请求异常,请求连接: https://api.sgroup.qq.com/channels/7150658/messages, 错误代码: 501, 返回内容: None, trace_id:None
|
||||
2022-12-08 17:22:03,924 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 17:22:04,671 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 17:22:04,672 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 17:22:04,673 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 17:22:04,673 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 17:22:04,856 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 17:22:04,958 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 17:22:04,959 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 17:52:04,868 [INFO] (gateway.py:54)on_closed [botpy] 关闭, 返回码: 4009, 返回信息: Session timed out
|
||||
2022-12-08 17:52:09,874 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 17:52:09,876 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 17:52:09,877 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 17:52:10,104 [INFO] (gateway.py:169)ws_resume [botpy] 重连启动...
|
||||
2022-12-08 17:52:10,170 [INFO] (gateway.py:85)on_message [botpy] 机器人重连成功!
|
||||
2022-12-08 17:52:10,171 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 18:00:00,757 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 18:00:01,443 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 18:00:01,443 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 18:00:01,444 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 18:00:01,445 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 18:00:01,602 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 18:00:01,823 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 18:00:01,824 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 18:03:13,211 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 18:03:14,082 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 18:03:14,084 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 18:03:14,084 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 18:03:14,085 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 18:03:14,289 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 18:03:14,498 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 18:03:14,499 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 18:16:29,246 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 18:16:30,054 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 18:16:30,055 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 18:16:30,056 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 18:16:30,056 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 18:16:30,293 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 18:16:30,424 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 18:16:30,424 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 18:16:41,898 [ERROR] (http.py:73)_handle_response [botpy] 接口请求异常,请求连接: https://api.sgroup.qq.com/channels/7150658/messages, 错误代码: 403, 返回内容: {'code': 304003, 'message': 'url not allowed'}, trace_id:3cc9fc95ac27cbbc1f1667f1aa11bf8d
|
||||
2022-12-08 18:18:16,615 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 18:18:17,399 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 18:18:17,400 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 18:18:17,400 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 18:18:17,401 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 18:18:17,606 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 18:18:17,731 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 18:18:17,732 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 18:19:07,357 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 18:19:07,941 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 18:19:07,942 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 18:19:07,942 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 18:19:07,943 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 18:19:08,247 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 18:19:08,335 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 18:19:08,336 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 18:20:46,416 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 18:20:47,023 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 18:20:47,023 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 18:20:47,024 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 18:20:47,025 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 18:20:47,475 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 18:20:47,640 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 18:20:47,641 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 18:21:24,437 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 18:21:24,991 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 18:21:24,992 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 18:21:24,993 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 18:21:24,993 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 18:21:25,165 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 18:21:25,265 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 18:21:25,266 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 18:24:18,469 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 18:24:19,076 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 18:24:19,077 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 18:24:19,077 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 18:24:19,078 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 18:24:19,252 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 18:24:19,339 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 18:24:19,341 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 18:27:13,898 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 18:27:14,553 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 18:27:14,554 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 18:27:14,554 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 18:27:14,555 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 18:27:14,747 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 18:27:14,850 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 18:27:14,851 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 18:30:47,647 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 18:30:48,327 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 18:30:48,328 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 18:30:48,329 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 18:30:48,330 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 18:30:48,736 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 18:30:48,873 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 18:30:48,874 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 18:31:57,250 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 18:31:57,955 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 18:31:57,956 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 18:31:57,957 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 18:31:57,957 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 18:31:58,165 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 18:31:58,269 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 18:31:58,270 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 19:01:58,099 [INFO] (gateway.py:54)on_closed [botpy] 关闭, 返回码: 4009, 返回信息: Session timed out
|
||||
2022-12-08 19:02:03,110 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 19:02:03,111 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 19:02:03,111 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 19:02:03,314 [INFO] (gateway.py:169)ws_resume [botpy] 重连启动...
|
||||
2022-12-08 19:02:03,381 [INFO] (gateway.py:85)on_message [botpy] 机器人重连成功!
|
||||
2022-12-08 19:02:03,382 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 19:32:03,274 [INFO] (gateway.py:54)on_closed [botpy] 关闭, 返回码: 4009, 返回信息: Session timed out
|
||||
2022-12-08 19:32:08,271 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 19:32:08,272 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 19:32:08,272 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 19:32:08,534 [INFO] (gateway.py:169)ws_resume [botpy] 重连启动...
|
||||
2022-12-08 19:32:08,604 [INFO] (gateway.py:85)on_message [botpy] 机器人重连成功!
|
||||
2022-12-08 19:32:08,605 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 20:02:08,495 [INFO] (gateway.py:54)on_closed [botpy] 关闭, 返回码: 4009, 返回信息: Session timed out
|
||||
2022-12-08 20:02:13,497 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 20:02:13,497 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 20:02:13,498 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 20:02:13,797 [INFO] (gateway.py:169)ws_resume [botpy] 重连启动...
|
||||
2022-12-08 20:02:13,914 [INFO] (gateway.py:85)on_message [botpy] 机器人重连成功!
|
||||
2022-12-08 20:02:13,915 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 20:31:53,159 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 20:31:58,306 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 20:31:58,307 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 20:31:58,308 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 20:31:58,308 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 20:31:58,748 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 20:31:58,924 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 20:31:58,925 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 20:34:26,596 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 20:34:27,610 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 20:34:27,611 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 20:34:27,613 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 20:34:27,613 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 20:34:27,919 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 20:34:28,022 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 20:34:28,023 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 20:35:47,952 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 20:35:48,499 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 20:35:48,500 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 20:35:48,500 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 20:35:48,501 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 20:35:48,723 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 20:35:48,793 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 20:35:48,794 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 20:55:03,450 [ERROR] (http.py:73)_handle_response [botpy] 接口请求异常,请求连接: https://api.sgroup.qq.com/channels/7150658/messages, 错误代码: 403, 返回内容: {'code': 304003, 'message': 'url not allowed'}, trace_id:c4c4d23f9b2829d03ae9a7dca0184fe9
|
||||
2022-12-08 21:05:48,678 [INFO] (gateway.py:54)on_closed [botpy] 关闭, 返回码: 4009, 返回信息: Session timed out
|
||||
2022-12-08 21:05:53,700 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 21:05:53,701 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 21:05:53,702 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 21:05:54,145 [INFO] (gateway.py:169)ws_resume [botpy] 重连启动...
|
||||
2022-12-08 21:05:54,232 [INFO] (gateway.py:85)on_message [botpy] 机器人重连成功!
|
||||
2022-12-08 21:05:54,233 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 21:07:39,468 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 21:07:40,244 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 21:07:40,245 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 21:07:40,246 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 21:07:40,247 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 21:07:40,553 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 21:07:40,659 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 21:07:40,660 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 21:30:11,249 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 21:30:12,217 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 21:30:12,218 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 21:30:12,219 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 21:30:12,219 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 21:30:12,627 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 21:30:12,730 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 21:30:12,731 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 21:36:34,660 [ERROR] (http.py:73)_handle_response [botpy] 接口请求异常,请求连接: https://api.sgroup.qq.com/channels/7150658/messages, 错误代码: 501, 返回内容: None, trace_id:None
|
||||
2022-12-08 21:38:39,294 [ERROR] (http.py:73)_handle_response [botpy] 接口请求异常,请求连接: https://api.sgroup.qq.com/channels/7150658/messages, 错误代码: 501, 返回内容: None, trace_id:None
|
||||
2022-12-08 21:39:43,233 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 21:39:43,878 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 21:39:43,879 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 21:39:43,880 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 21:39:43,880 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 21:39:44,099 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 21:39:44,279 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 21:39:44,281 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 21:40:38,103 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 21:40:39,100 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 21:40:39,101 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 21:40:39,102 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 21:40:39,102 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 21:40:39,402 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 21:40:39,502 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 21:40:39,503 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 21:40:52,805 [ERROR] (http.py:73)_handle_response [botpy] 接口请求异常,请求连接: https://api.sgroup.qq.com/channels/7150658/messages, 错误代码: 501, 返回内容: None, trace_id:None
|
||||
2022-12-08 21:41:39,703 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 21:41:40,399 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 21:41:40,400 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 21:41:40,401 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 21:41:40,401 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 21:41:40,644 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 21:41:40,740 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 21:41:40,741 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 21:41:56,705 [ERROR] (http.py:73)_handle_response [botpy] 接口请求异常,请求连接: https://api.sgroup.qq.com/channels/7150658/messages, 错误代码: 501, 返回内容: None, trace_id:None
|
||||
2022-12-08 21:42:55,625 [INFO] (client.py:159)_bot_login [botpy] 登录机器人账号中...
|
||||
2022-12-08 21:42:56,278 [INFO] (client.py:178)_bot_init [botpy] 程序启动...
|
||||
2022-12-08 21:42:56,279 [INFO] (connection.py:59)multi_run [botpy] 最大并发连接数: 1, 启动会话数: 1
|
||||
2022-12-08 21:42:56,280 [INFO] (client.py:236)bot_connect [botpy] 会话启动中...
|
||||
2022-12-08 21:42:56,281 [INFO] (gateway.py:110)ws_connect [botpy] 启动中...
|
||||
2022-12-08 21:42:56,718 [INFO] (gateway.py:136)ws_identify [botpy] 鉴权中...
|
||||
2022-12-08 21:42:56,819 [INFO] (gateway.py:80)on_message [botpy] 机器人「SoGPT-测试中」启动成功!
|
||||
2022-12-08 21:42:56,820 [INFO] (gateway.py:217)_send_heart [botpy] 心跳维持启动...
|
||||
2022-12-08 21:43:09,794 [ERROR] (http.py:73)_handle_response [botpy] 接口请求异常,请求连接: https://api.sgroup.qq.com/channels/7150658/messages, 错误代码: 501, 返回内容: None, trace_id:None
|
||||
+129
-21
@@ -1,29 +1,137 @@
|
||||
openai:
|
||||
# 注意:在1.7版本已支持多key自动切换,方法:
|
||||
# key:
|
||||
# - xxxxx
|
||||
# - xxxxxx
|
||||
# 在下方非注释的地方使用以上格式
|
||||
key:
|
||||
-
|
||||
chatGPTConfigs:
|
||||
engine: text-davinci-003
|
||||
max_tokens: 800
|
||||
temperature: 0.8
|
||||
top_p: 1
|
||||
frequency_penalty: 0.4
|
||||
presence_penalty: 0.3
|
||||
total_tokens_limit: 700
|
||||
# 如果你不知道怎么部署,请查看https://soulter.top/posts/qpdg.html
|
||||
# 不一定需要key了,如果你没有key但有openAI账号或者必应账号,可以考虑使用下面的逆向库
|
||||
|
||||
|
||||
###############平台设置#################
|
||||
|
||||
# QQ频道机器人
|
||||
# QQ开放平台的appid和令牌
|
||||
# q.qq.com
|
||||
# enable为true则启用,false则不启用
|
||||
qqbot:
|
||||
enable: true
|
||||
appid:
|
||||
token:
|
||||
|
||||
# QQ机器人
|
||||
# enable为true则启用,false则不启用
|
||||
# 需要安装GO-CQHTTP配合使用。
|
||||
# 文档:https://docs.go-cqhttp.org/
|
||||
# 请将go-cqhttp的配置文件的sever部分粘贴为以下内容,否则无法使用
|
||||
# 请先启动go-cqhttp再启动本程序
|
||||
#
|
||||
# servers:
|
||||
# - http:
|
||||
# host: 127.0.0.1
|
||||
# version: 0
|
||||
# port: 5700
|
||||
# timeout: 5
|
||||
# - ws:
|
||||
# address: 127.0.0.1:6700
|
||||
# middlewares:
|
||||
# <<: *default
|
||||
gocqbot:
|
||||
enable: false
|
||||
|
||||
# 设置是否一个人一个会话
|
||||
uniqueSessionMode: false
|
||||
|
||||
# QChannelBot 的版本
|
||||
version: 1.7 beta
|
||||
|
||||
# QChannelBot 的版本,请勿修改此字段,否则可能产生一些bug
|
||||
version: 3.0
|
||||
# [Beta] 转储历史记录时间间隔(分钟)
|
||||
dump_history_interval: 10
|
||||
dump_history_interval: 10
|
||||
# 一个用户只能在time秒内发送count条消息
|
||||
limit:
|
||||
time: 60
|
||||
count: 5
|
||||
# 公告
|
||||
notice: "此机器人由Github项目QQChannelChatGPT驱动。"
|
||||
# 是否打开私信功能
|
||||
# 设置为true则频道成员可以私聊机器人。
|
||||
# 设置为false则频道成员不能私聊机器人。
|
||||
direct_message_mode: true
|
||||
|
||||
# 系统代理
|
||||
# http_proxy: http://localhost:7890
|
||||
# https_proxy: http://localhost:7890
|
||||
|
||||
# 自定义回复前缀,如[Rev]或其他,务必加引号以防止不必要的bug。
|
||||
reply_prefix:
|
||||
openai_official: "[GPT]"
|
||||
rev_chatgpt: "[Rev]"
|
||||
rev_edgegpt: "[RevBing]"
|
||||
|
||||
# 百度内容审核服务
|
||||
# 新用户免费5万次调用。https://cloud.baidu.com/doc/ANTIPORN/index.html
|
||||
baidu_aip:
|
||||
enable: false
|
||||
app_id:
|
||||
api_key:
|
||||
secret_key:
|
||||
|
||||
|
||||
|
||||
|
||||
###############语言模型设置#################
|
||||
|
||||
|
||||
# OpenAI官方API
|
||||
# 注意:已支持多key自动切换,方法:
|
||||
# key:
|
||||
# - sk-xxxxxx
|
||||
# - sk-xxxxxx
|
||||
# 在下方非注释的地方使用以上格式
|
||||
# 关于api_base:可以使用一些云函数(如腾讯、阿里)来避免国内被墙的问题。
|
||||
# 详见:
|
||||
# https://github.com/Ice-Hazymoon/openai-scf-proxy
|
||||
# https://github.com/Soulter/QQChannelChatGPT/issues/42
|
||||
# 设置为none则表示使用官方默认api地址
|
||||
openai:
|
||||
key:
|
||||
-
|
||||
api_base: none
|
||||
# 这里是GPT配置,语言模型默认使用gpt-3.5-turbo
|
||||
chatGPTConfigs:
|
||||
model: gpt-3.5-turbo
|
||||
max_tokens: 3000
|
||||
temperature: 0.9
|
||||
top_p: 1
|
||||
frequency_penalty: 0
|
||||
presence_penalty: 0
|
||||
|
||||
total_tokens_limit: 5000
|
||||
|
||||
# 逆向文心一言【暂时不可用,请勿使用】
|
||||
rev_ernie:
|
||||
enable: false
|
||||
|
||||
# 逆向New Bing
|
||||
# 需要在项目根目录下创建cookies.json并粘贴cookies进去。
|
||||
# 详见:https://soulter.top/posts/qpdg.html
|
||||
rev_edgegpt:
|
||||
enable: false
|
||||
|
||||
# 逆向ChatGPT库
|
||||
# https://github.com/acheong08/ChatGPT
|
||||
# 优点:免费(无免费额度限制);
|
||||
# 缺点:速度相对慢。OpenAI 速率限制:免费帐户每小时 50 个请求。您可以通过多帐户循环来绕过它
|
||||
# enable设置为true后,将会停止使用上面正常的官方API调用而使用本逆向项目
|
||||
#
|
||||
# 多账户可以保证每个请求都能得到及时的回复。
|
||||
# 关于account的格式
|
||||
# account:
|
||||
# - email: 第1个账户
|
||||
# password: 第1个账户密码
|
||||
# - email: 第2个账户
|
||||
# password: 第2个账户密码
|
||||
# - ....
|
||||
# 支持使用access_token登录
|
||||
# 例:
|
||||
# - session_token: xxxxx
|
||||
# - access_token: xxxx
|
||||
# 请严格按照上面这个格式填写。
|
||||
# 逆向ChatGPT库的email-password登录方式不工作,建议使用access_token登录
|
||||
# 获取access_token的方法,详见:https://soulter.top/posts/qpdg.html
|
||||
rev_ChatGPT:
|
||||
enable: false
|
||||
account:
|
||||
- access_token:
|
||||
Binary file not shown.
@@ -1,169 +0,0 @@
|
||||
import openai
|
||||
import yaml
|
||||
from util.errors.errors import PromptExceededError
|
||||
import json
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
|
||||
inst = None
|
||||
# 适配pyinstaller
|
||||
abs_path = os.path.dirname(os.path.realpath(sys.argv[0])) + '/'
|
||||
key_record_path = abs_path+'chatgpt_key_record'
|
||||
|
||||
class ChatGPT:
|
||||
def __init__(self):
|
||||
self.key_list = []
|
||||
with open(abs_path+"configs/config.yaml", 'r', encoding='utf-8') as ymlfile:
|
||||
cfg = yaml.safe_load(ymlfile)
|
||||
if cfg['openai']['key'] != '' or cfg['openai']['key'] != '修改我!!':
|
||||
print("读取ChatGPT Key成功")
|
||||
self.key_list = cfg['openai']['key']
|
||||
# openai.api_key = cfg['openai']['key']
|
||||
else:
|
||||
input("请先去完善ChatGPT的Key。详情请前往https://beta.openai.com/account/api-keys")
|
||||
|
||||
# init key record
|
||||
self.init_key_record()
|
||||
|
||||
chatGPT_configs = cfg['openai']['chatGPTConfigs']
|
||||
print(f'加载ChatGPTConfigs: {chatGPT_configs}')
|
||||
self.chatGPT_configs = chatGPT_configs
|
||||
self.openai_configs = cfg['openai']
|
||||
|
||||
def chat(self, prompt, image_mode = False):
|
||||
try:
|
||||
if not image_mode:
|
||||
response = openai.Completion.create(
|
||||
prompt=prompt,
|
||||
**self.chatGPT_configs
|
||||
)
|
||||
else:
|
||||
response = openai.Image.create(
|
||||
prompt=prompt,
|
||||
n=1,
|
||||
size="512x512",
|
||||
)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
if 'You exceeded' in str(e) or 'Billing hard limit has been reached' in str(e) or 'No API key provided.' in str(e):
|
||||
print("当前Key已超额,正在切换")
|
||||
self.key_stat[openai.api_key]['exceed'] = True
|
||||
self.save_key_record()
|
||||
|
||||
response, is_switched = self.handle_switch_key(prompt)
|
||||
if not is_switched:
|
||||
# 所有Key都超额
|
||||
raise e
|
||||
else:
|
||||
if not image_mode:
|
||||
response = openai.Completion.create(
|
||||
prompt=prompt,
|
||||
**self.chatGPT_configs
|
||||
)
|
||||
else:
|
||||
response = openai.Image.create(
|
||||
prompt=prompt,
|
||||
n=1,
|
||||
size="512x512",
|
||||
)
|
||||
if not image_mode:
|
||||
self.key_stat[openai.api_key]['used'] += response['usage']['total_tokens']
|
||||
self.save_key_record()
|
||||
print("[ChatGPT] "+str(response["choices"][0]["text"]))
|
||||
return str(response["choices"][0]["text"]).strip(), response['usage']['total_tokens']
|
||||
else:
|
||||
return response['data'][0]['url']
|
||||
|
||||
def handle_switch_key(self, prompt):
|
||||
while True:
|
||||
is_all_exceed = True
|
||||
for key in self.key_stat:
|
||||
if not self.key_stat[key]['exceed']:
|
||||
is_all_exceed = False
|
||||
openai.api_key = key
|
||||
print(f"切换到Key: {key}, 已使用token: {self.key_stat[key]['used']}")
|
||||
if prompt != '':
|
||||
try:
|
||||
response = openai.Completion.create(
|
||||
prompt=prompt,
|
||||
**self.chatGPT_configs
|
||||
)
|
||||
return response, True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
if 'You exceeded' in str(e):
|
||||
print("当前Key已超额,正在切换")
|
||||
self.key_stat[openai.api_key]['exceed'] = True
|
||||
self.save_key_record()
|
||||
time.sleep(1)
|
||||
continue
|
||||
else:
|
||||
return True
|
||||
if is_all_exceed:
|
||||
print("所有Key已超额")
|
||||
return None, False
|
||||
|
||||
def getConfigs(self):
|
||||
return self.openai_configs
|
||||
|
||||
def save_key_record(self):
|
||||
with open(key_record_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(self.key_stat, f)
|
||||
|
||||
def get_key_stat(self):
|
||||
return self.key_stat
|
||||
def get_key_list(self):
|
||||
return self.key_list
|
||||
|
||||
# 添加key
|
||||
def append_key(self, key, sponsor):
|
||||
self.key_list.append(key)
|
||||
self.key_stat[key] = {'exceed': False, 'used': 0, 'sponsor': sponsor}
|
||||
self.save_key_record()
|
||||
self.init_key_record()
|
||||
# 检查key是否可用
|
||||
def check_key(self, key):
|
||||
pre_key = openai.api_key
|
||||
openai.api_key = key
|
||||
try:
|
||||
openai.Completion.create(
|
||||
prompt="1",
|
||||
**self.chatGPT_configs
|
||||
)
|
||||
openai.api_key = pre_key
|
||||
return True
|
||||
except Exception as e:
|
||||
pass
|
||||
openai.api_key = pre_key
|
||||
return False
|
||||
|
||||
#将key_list的key转储到key_record中,并记录相关数据
|
||||
def init_key_record(self):
|
||||
if not os.path.exists(key_record_path):
|
||||
with open(key_record_path, 'w', encoding='utf-8') as f:
|
||||
json.dump({}, f)
|
||||
with open(key_record_path, 'r', encoding='utf-8') as keyfile:
|
||||
try:
|
||||
self.key_stat = json.load(keyfile)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.key_stat = {}
|
||||
finally:
|
||||
for key in self.key_list:
|
||||
if key not in self.key_stat:
|
||||
self.key_stat[key] = {'exceed': False, 'used': 0}
|
||||
# if openai.api_key is None:
|
||||
# openai.api_key = key
|
||||
else:
|
||||
# if self.key_stat[key]['exceed']:
|
||||
# print(f"Key: {key} 已超额")
|
||||
# continue
|
||||
# else:
|
||||
# if openai.api_key is None:
|
||||
# openai.api_key = key
|
||||
# print(f"使用Key: {key}, 已使用token: {self.key_stat[key]['used']}")
|
||||
pass
|
||||
if openai.api_key == None:
|
||||
self.handle_switch_key("")
|
||||
self.save_key_record()
|
||||
Binary file not shown.
+413
-467
@@ -1,21 +1,26 @@
|
||||
import botpy
|
||||
from botpy.message import Message
|
||||
import yaml
|
||||
from botpy.types.message import Reference
|
||||
import re
|
||||
from util.errors.errors import PromptExceededError
|
||||
from botpy.message import DirectMessage
|
||||
import json
|
||||
import threading
|
||||
import asyncio
|
||||
import time
|
||||
from cores.database.conn import dbConn
|
||||
import requests
|
||||
import util.unfit_words as uw
|
||||
import os
|
||||
import sys
|
||||
from cores.qqbot.personality import personalities
|
||||
from addons.baidu_aip_judge import BaiduJudge
|
||||
from model.platform.qqchan import QQChan
|
||||
from model.platform.qq import QQ
|
||||
from nakuru import (
|
||||
CQHTTP,
|
||||
GroupMessage,
|
||||
)
|
||||
from nakuru.entities.components import Plain
|
||||
|
||||
history_dump_interval = 10
|
||||
# QQBotClient实例
|
||||
client = ''
|
||||
# ChatGPT实例
|
||||
@@ -48,30 +53,55 @@ frequency_count = 2
|
||||
# 公告(可自定义):
|
||||
announcement = ""
|
||||
|
||||
# 人格信息
|
||||
now_personality = {}
|
||||
# 机器人私聊模式
|
||||
direct_message_mode = True
|
||||
|
||||
# 适配pyinstaller
|
||||
abs_path = os.path.dirname(os.path.realpath(sys.argv[0])) + '/'
|
||||
|
||||
# 版本
|
||||
version = '3.0'
|
||||
|
||||
# 语言模型
|
||||
REV_CHATGPT = 'rev_chatgpt'
|
||||
OPENAI_OFFICIAL = 'openai_official'
|
||||
REV_ERNIE = 'rev_ernie'
|
||||
REV_EDGEGPT = 'rev_edgegpt'
|
||||
provider = None
|
||||
chosen_provider = None
|
||||
|
||||
# 逆向库对象
|
||||
rev_chatgpt = None
|
||||
# gpt配置信息
|
||||
gpt_config = {}
|
||||
# 百度内容审核实例
|
||||
baidu_judge = None
|
||||
# 回复前缀
|
||||
reply_prefix = {}
|
||||
# 关键词回复
|
||||
keywords = {}
|
||||
|
||||
# QQ频道机器人
|
||||
qqchannel_bot = None
|
||||
PLATFORM_QQCHAN = 'qqchan'
|
||||
qqchan_loop = None
|
||||
|
||||
# QQ机器人
|
||||
gocq_bot = None
|
||||
PLATFORM_GOCQ = 'gocq'
|
||||
gocq_app = CQHTTP(
|
||||
host="127.0.0.1",
|
||||
port=6700,
|
||||
http_port=5700,
|
||||
)
|
||||
gocq_loop = None
|
||||
|
||||
bing_cache_loop = None
|
||||
|
||||
|
||||
def new_sub_thread(func, args=()):
|
||||
thread = threading.Thread(target=func, args=args, daemon=True)
|
||||
thread.start()
|
||||
|
||||
class botClient(botpy.Client):
|
||||
# 收到At消息
|
||||
async def on_at_message_create(self, message: Message):
|
||||
toggle_count(at=True, message=message)
|
||||
# executor.submit(oper_msg, message, True)
|
||||
new_sub_thread(oper_msg, (message, True))
|
||||
# await oper_msg(message=message, at=True)
|
||||
|
||||
# 收到私聊消息
|
||||
async def on_direct_message_create(self, message: DirectMessage):
|
||||
toggle_count(at=False, message=message)
|
||||
# executor.submit(oper_msg, message, True)
|
||||
# await oper_msg(message=message, at=False)
|
||||
new_sub_thread(oper_msg, (message, False))
|
||||
thread.start()
|
||||
|
||||
# 写入统计信息
|
||||
def toggle_count(at: bool, message):
|
||||
@@ -93,33 +123,10 @@ def toggle_count(at: bool, message):
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
# 转储历史记录的定时器~ Soulter
|
||||
def dump_history():
|
||||
time.sleep(10)
|
||||
global session_dict, history_dump_interval
|
||||
db = dbConn()
|
||||
while True:
|
||||
try:
|
||||
# print("转储历史记录...")
|
||||
for key in session_dict:
|
||||
# print("TEST: "+str(db.get_session(key)))
|
||||
data = session_dict[key]
|
||||
data_json = {
|
||||
'data': data
|
||||
}
|
||||
if db.check_session(key):
|
||||
db.update_session(key, json.dumps(data_json))
|
||||
else:
|
||||
db.insert_session(key, json.dumps(data_json))
|
||||
# print("转储历史记录完毕")
|
||||
except BaseException as e:
|
||||
print(e)
|
||||
# 每隔10分钟转储一次
|
||||
time.sleep(10*history_dump_interval)
|
||||
|
||||
# 上传统计信息
|
||||
# 上传统计信息并检查更新
|
||||
def upload():
|
||||
global object_id
|
||||
global version
|
||||
while True:
|
||||
addr = ''
|
||||
try:
|
||||
@@ -136,7 +143,7 @@ def upload():
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
key_stat = chatgpt.get_key_stat()
|
||||
d = {"data": {"guild_count": guild_count, "guild_msg_count": guild_msg_count, "guild_direct_msg_count": guild_direct_msg_count, "session_count": session_count, 'addr': addr, 'winver': '2.21', 'key_stat':key_stat}}
|
||||
d = {"data": {'version': version, "guild_count": guild_count, "guild_msg_count": guild_msg_count, "guild_direct_msg_count": guild_direct_msg_count, "session_count": session_count, 'addr': addr, 'key_stat':key_stat}}
|
||||
d = json.dumps(d).encode("utf-8")
|
||||
res = requests.put(f'https://uqfxtww1.lc-cn-n1-shared.com/1.1/classes/bot_record/{object_id}', headers = headers, data = d)
|
||||
if json.loads(res.text)['code'] == 1:
|
||||
@@ -155,41 +162,61 @@ def upload():
|
||||
'''
|
||||
初始化机器人
|
||||
'''
|
||||
def initBot(chatgpt_inst):
|
||||
global chatgpt
|
||||
chatgpt = chatgpt_inst
|
||||
global max_tokens
|
||||
max_tokens = int(chatgpt_inst.getConfigs()['total_tokens_limit'])
|
||||
global now_personality
|
||||
def initBot(cfg, prov):
|
||||
global chatgpt, provider, rev_chatgpt, baidu_judge, rev_edgegpt, chosen_provider
|
||||
global reply_prefix, gpt_config, config, uniqueSession, frequency_count, frequency_time,announcement, direct_message_mode, version
|
||||
global command_openai_official, command_rev_chatgpt, command_rev_edgegpt,reply_prefix, keywords
|
||||
provider = prov
|
||||
config = cfg
|
||||
if 'reply_prefix' in cfg:
|
||||
reply_prefix = cfg['reply_prefix']
|
||||
|
||||
# 语言模型提供商
|
||||
if REV_CHATGPT in prov:
|
||||
if 'account' in cfg['rev_ChatGPT']:
|
||||
from model.provider.provider_rev_chatgpt import ProviderRevChatGPT
|
||||
from model.command.command_rev_chatgpt import CommandRevChatGPT
|
||||
rev_chatgpt = ProviderRevChatGPT(cfg['rev_ChatGPT'])
|
||||
command_rev_chatgpt = CommandRevChatGPT(cfg['rev_ChatGPT'])
|
||||
chosen_provider = REV_CHATGPT
|
||||
else:
|
||||
input("[System-err] 请退出本程序, 然后在配置文件中填写rev_ChatGPT相关配置")
|
||||
|
||||
if REV_EDGEGPT in prov:
|
||||
from model.provider.provider_rev_edgegpt import ProviderRevEdgeGPT
|
||||
from model.command.command_rev_edgegpt import CommandRevEdgeGPT
|
||||
rev_edgegpt = ProviderRevEdgeGPT()
|
||||
command_rev_edgegpt = CommandRevEdgeGPT(rev_edgegpt)
|
||||
chosen_provider = REV_EDGEGPT
|
||||
if OPENAI_OFFICIAL in prov:
|
||||
from model.provider.provider_openai_official import ProviderOpenAIOfficial
|
||||
from model.command.command_openai_official import CommandOpenAIOfficial
|
||||
chatgpt = ProviderOpenAIOfficial(cfg['openai'])
|
||||
command_openai_official = CommandOpenAIOfficial(chatgpt)
|
||||
chosen_provider = OPENAI_OFFICIAL
|
||||
|
||||
# 读取历史记录 Soulter
|
||||
try:
|
||||
db1 = dbConn()
|
||||
for session in db1.get_all_session():
|
||||
session_dict[session[0]] = json.loads(session[1])['data']
|
||||
print("[System] 历史记录读取成功喵")
|
||||
except BaseException as e:
|
||||
print("[System] 历史记录读取失败: " + str(e))
|
||||
# 得到关键词
|
||||
if os.path.exists("keyword.json"):
|
||||
with open("keyword.json", 'r', encoding='utf-8') as f:
|
||||
keywords = json.load(f)
|
||||
|
||||
# 读统计信息
|
||||
global stat_file
|
||||
if not os.path.exists(abs_path+"configs/stat"):
|
||||
with open(abs_path+"configs/stat", 'w', encoding='utf-8') as f:
|
||||
json.dump({}, f)
|
||||
stat_file = open(abs_path+"configs/stat", 'r', encoding='utf-8')
|
||||
global count
|
||||
res = stat_file.read()
|
||||
if res == '':
|
||||
count = {}
|
||||
else:
|
||||
# 检查provider设置偏好
|
||||
if os.path.exists("provider_preference.txt"):
|
||||
with open("provider_preference.txt", 'r', encoding='utf-8') as f:
|
||||
res = f.read()
|
||||
if res in prov:
|
||||
chosen_provider = res
|
||||
|
||||
# 百度内容审核
|
||||
if 'baidu_aip' in cfg and 'enable' in cfg['baidu_aip'] and cfg['baidu_aip']['enable']:
|
||||
try:
|
||||
count = json.loads(res)
|
||||
except BaseException:
|
||||
pass
|
||||
# 创建转储定时器线程
|
||||
threading.Thread(target=dump_history, daemon=True).start()
|
||||
|
||||
baidu_judge = BaiduJudge(cfg['baidu_aip'])
|
||||
print("[System] 百度内容审核初始化成功")
|
||||
except BaseException as e:
|
||||
input("[System] 百度内容审核初始化失败: " + str(e))
|
||||
exit()
|
||||
|
||||
# 统计上传
|
||||
if is_upload_log:
|
||||
# 读取object_id
|
||||
global object_id
|
||||
@@ -201,106 +228,85 @@ def initBot(chatgpt_inst):
|
||||
object_id_file.close()
|
||||
# 创建上传定时器线程
|
||||
threading.Thread(target=upload, daemon=True).start()
|
||||
|
||||
# 得到私聊模式配置
|
||||
if 'direct_message_mode' in cfg:
|
||||
direct_message_mode = cfg['direct_message_mode']
|
||||
print("[System] 私聊功能: "+str(direct_message_mode))
|
||||
|
||||
global config, uniqueSession, history_dump_interval, frequency_count, frequency_time,announcement
|
||||
with open(abs_path+"configs/config.yaml", 'r', encoding='utf-8') as ymlfile:
|
||||
cfg = yaml.safe_load(ymlfile)
|
||||
config = cfg
|
||||
# 得到发言频率配置
|
||||
if 'limit' in cfg:
|
||||
print('[System] 发言频率配置: '+str(cfg['limit']))
|
||||
if 'count' in cfg['limit']:
|
||||
frequency_count = cfg['limit']['count']
|
||||
if 'time' in cfg['limit']:
|
||||
frequency_time = cfg['limit']['time']
|
||||
|
||||
# 得到公告配置
|
||||
if 'notice' in cfg:
|
||||
print('[System] 公告配置: '+cfg['notice'])
|
||||
announcement += cfg['notice']
|
||||
try:
|
||||
if 'uniqueSessionMode' in cfg and cfg['uniqueSessionMode']:
|
||||
uniqueSession = True
|
||||
else:
|
||||
uniqueSession = False
|
||||
print("[System] 独立会话: " + str(uniqueSession))
|
||||
if 'dump_history_interval' in cfg:
|
||||
print("[System] 历史记录转储时间周期: " + cfg['dump_history_interval'] + "分钟")
|
||||
except BaseException:
|
||||
print("[System-Error] 读取uniqueSessionMode/version/dump_history_interval配置文件失败, 使用默认值。")
|
||||
|
||||
# 得到发言频率配置
|
||||
if 'limit' in cfg:
|
||||
print('[System] 发言频率配置: '+str(cfg['limit']))
|
||||
if 'count' in cfg['limit']:
|
||||
frequency_count = cfg['limit']['count']
|
||||
if 'time' in cfg['limit']:
|
||||
frequency_time = cfg['limit']['time']
|
||||
|
||||
announcement += '[QQChannelChatGPT项目]\n所有回答与腾讯公司无关。出现问题请前往[ChatGPT机器人]官方频道\n\n'
|
||||
# 得到公告配置
|
||||
if 'notice' in cfg:
|
||||
print('[System] 公告配置: '+cfg['notice'])
|
||||
announcement += cfg['notice']
|
||||
try:
|
||||
if 'uniqueSessionMode' in cfg and cfg['uniqueSessionMode']:
|
||||
uniqueSession = True
|
||||
else:
|
||||
uniqueSession = False
|
||||
print("[System] 独立会话: " + str(uniqueSession))
|
||||
if 'dump_history_interval' in cfg:
|
||||
history_dump_interval = int(cfg['dump_history_interval'])
|
||||
print("[System] 历史记录转储时间周期: " + str(history_dump_interval) + "分钟")
|
||||
except BaseException:
|
||||
print("[System-Error] 读取uniqueSessionMode/version/dump_history_interval配置文件失败, 使用默认值。")
|
||||
print(f"[System] QQ开放平台AppID: {cfg['qqbot']['appid']} 令牌: {cfg['qqbot']['token']}")
|
||||
|
||||
print(f"[System] QQ开放平台AppID: {cfg['qqbot']['appid']} 令牌: {cfg['qqbot']['token']}")
|
||||
print("\n[System] 如果有任何问题, 请在 https://github.com/Soulter/QQChannelChatGPT 上提交issue说明问题!或者添加QQ:905617992")
|
||||
print("[System] 请给 https://github.com/Soulter/QQChannelChatGPT 点个star!")
|
||||
|
||||
print("[System] 如果有任何问题,请在https://github.com/Soulter/QQChannelChatGPT上提交issue说明问题!或者添加QQ:905617992\n")
|
||||
try:
|
||||
run_bot(cfg['qqbot']['appid'], cfg['qqbot']['token'])
|
||||
except BaseException as e:
|
||||
input(f"\n[System-Error] 启动QQ机器人时出现错误,原因如下:{e}\n可能是没有填写QQBOT appid和token?请在config中完善你的appid和token\n配置教程:https://soulter.top/posts/qpdg.html\n")
|
||||
|
||||
'''
|
||||
启动机器人
|
||||
'''
|
||||
def run_bot(appid, token):
|
||||
thread_inst = None
|
||||
|
||||
# QQ频道
|
||||
if 'qqbot' in cfg and cfg['qqbot']['enable']:
|
||||
print("[System] 启用QQ频道机器人")
|
||||
global qqchannel_bot, qqchan_loop
|
||||
qqchannel_bot = QQChan()
|
||||
qqchan_loop = asyncio.new_event_loop()
|
||||
thread_inst = threading.Thread(target=run_qqchan_bot, args=(cfg, qqchan_loop, qqchannel_bot), daemon=False)
|
||||
thread_inst.start()
|
||||
# thread.join()
|
||||
|
||||
# GOCQ
|
||||
if 'gocqbot' in cfg and cfg['gocqbot']['enable']:
|
||||
print("[System] 启用QQ机器人")
|
||||
global gocq_app, gocq_bot, gocq_loop
|
||||
gocq_bot = QQ()
|
||||
gocq_loop = asyncio.new_event_loop()
|
||||
thread_inst = threading.Thread(target=run_gocq_bot, args=(gocq_loop, gocq_bot, gocq_app), daemon=False)
|
||||
thread_inst.start()
|
||||
|
||||
if thread_inst == None:
|
||||
input("[System-Error] 没有启用任何机器人,程序退出")
|
||||
exit()
|
||||
|
||||
thread_inst.join()
|
||||
|
||||
def run_qqchan_bot(cfg, loop, qqchannel_bot):
|
||||
asyncio.set_event_loop(loop)
|
||||
intents = botpy.Intents(public_guild_messages=True, direct_message=True)
|
||||
global client
|
||||
client = botClient(intents=intents)
|
||||
client.run(appid=appid, token=token)
|
||||
try:
|
||||
qqchannel_bot.run_bot(client, cfg['qqbot']['appid'], cfg['qqbot']['token'])
|
||||
except BaseException as e:
|
||||
input(f"\n[System-Error] 启动QQ频道机器人时出现错误,原因如下:{e}\n可能是没有填写QQBOT appid和token?请在config中完善你的appid和token\n配置教程:https://soulter.top/posts/qpdg.html\n")
|
||||
|
||||
'''
|
||||
得到OpenAI的回复
|
||||
'''
|
||||
def get_chatGPT_response(prompts_str, image_mode=False):
|
||||
res = ''
|
||||
usage = ''
|
||||
if not image_mode:
|
||||
res, usage = chatgpt.chat(prompts_str)
|
||||
# 处理结果文本
|
||||
chatgpt_res = res.strip()
|
||||
return res, usage
|
||||
else:
|
||||
res = chatgpt.chat(prompts_str, image_mode = True)
|
||||
return res
|
||||
|
||||
'''
|
||||
回复QQ消息
|
||||
'''
|
||||
def send_qq_msg(message, res, image_mode=False):
|
||||
if not image_mode:
|
||||
try:
|
||||
asyncio.run_coroutine_threadsafe(message.reply(content=res), client.loop)
|
||||
except BaseException as e:
|
||||
raise e
|
||||
else:
|
||||
asyncio.run_coroutine_threadsafe(message.reply(image=res, content=""), client.loop)
|
||||
|
||||
|
||||
'''
|
||||
获取缓存的会话
|
||||
'''
|
||||
def get_prompts_by_cache_list(cache_data_list, divide=False, paging=False, size=5, page=1):
|
||||
prompts = ""
|
||||
if paging:
|
||||
page_begin = (page-1)*size
|
||||
page_end = page*size
|
||||
if page_begin < 0:
|
||||
page_begin = 0
|
||||
if page_end > len(cache_data_list):
|
||||
page_end = len(cache_data_list)
|
||||
cache_data_list = cache_data_list[page_begin:page_end]
|
||||
for item in cache_data_list:
|
||||
prompts += str(item['prompt'])
|
||||
if divide:
|
||||
prompts += "----------\n"
|
||||
return prompts
|
||||
|
||||
def get_user_usage_tokens(cache_list):
|
||||
usage_tokens = 0
|
||||
for item in cache_list:
|
||||
usage_tokens += int(item['single_tokens'])
|
||||
return usage_tokens
|
||||
def run_gocq_bot(loop, gocq_bot, gocq_app):
|
||||
asyncio.set_event_loop(loop)
|
||||
global gocq_client
|
||||
gocq_client = gocqClient()
|
||||
try:
|
||||
gocq_bot.run_bot(gocq_app)
|
||||
except BaseException as e:
|
||||
input("启动QQ机器人出现错误"+str(e))
|
||||
|
||||
'''
|
||||
检查发言频率
|
||||
@@ -323,205 +329,245 @@ def check_frequency(id) -> bool:
|
||||
user_frequency[id] = t
|
||||
return True
|
||||
|
||||
def save_provider_preference(chosen_provider):
|
||||
with open('provider_preference.txt', 'w') as f:
|
||||
f.write(chosen_provider)
|
||||
|
||||
|
||||
'''
|
||||
通用回复方法
|
||||
'''
|
||||
def send_message(platform, message, res, msg_ref = None, image = None, gocq_loop = None, qqchannel_bot = None, gocq_bot = None):
|
||||
if platform == PLATFORM_QQCHAN:
|
||||
if image != None:
|
||||
qqchannel_bot.send_qq_msg(message, res, image_mode=True, msg_ref=msg_ref)
|
||||
else:
|
||||
qqchannel_bot.send_qq_msg(message, res, msg_ref=msg_ref)
|
||||
if platform == PLATFORM_GOCQ: asyncio.run_coroutine_threadsafe(gocq_bot.send_qq_msg(message, res), gocq_loop).result()
|
||||
|
||||
'''
|
||||
处理消息
|
||||
'''
|
||||
def oper_msg(message, at=False, loop=None):
|
||||
global session_dict
|
||||
print("[QQBOT] 接收到消息:"+ str(message.content))
|
||||
def oper_msg(message, at=False, msg_ref = None, platform = None):
|
||||
global session_dict, provider
|
||||
qq_msg = ''
|
||||
session_id = ''
|
||||
name = ''
|
||||
user_id = message.author.id
|
||||
user_name = message.author.username
|
||||
user_id = ''
|
||||
user_name = ''
|
||||
global chosen_provider, reply_prefix, keywords, qqchannel_bot, gocq_bot, gocq_loop, bing_cache_loop
|
||||
role = "member" # 角色
|
||||
hit = False # 是否命中指令
|
||||
command_result = () # 调用指令返回的结果
|
||||
|
||||
if platform == PLATFORM_QQCHAN:
|
||||
print("[QQCHAN-BOT] 接收到消息:"+ str(message.content))
|
||||
user_id = message.author.id
|
||||
user_name = message.author.username
|
||||
global qqchan_loop
|
||||
if platform == PLATFORM_GOCQ:
|
||||
print("[GOCQ-BOT] 接收到消息:"+ str(message.message[0].text))
|
||||
user_id = message.group_id
|
||||
user_name = message.group_id
|
||||
global gocq_loop
|
||||
|
||||
# 检查发言频率
|
||||
if not check_frequency(user_id):
|
||||
send_qq_msg(message, f'{user_name}的发言超过频率限制(╯▔皿▔)╯。\n{frequency_time}秒内只能提问{frequency_count}次。')
|
||||
qqchannel_bot.send_qq_msg(message, f'{user_name}的发言超过频率限制(╯▔皿▔)╯。\n{frequency_time}秒内只能提问{frequency_count}次。')
|
||||
return
|
||||
|
||||
logf.write("[QQBOT] "+ str(message.content)+'\n')
|
||||
if platform == PLATFORM_QQCHAN:
|
||||
if at:
|
||||
# 频道内
|
||||
# 过滤@
|
||||
qq_msg = message.content
|
||||
lines = qq_msg.splitlines()
|
||||
for i in range(len(lines)):
|
||||
lines[i] = re.sub(r"<@!\d+>", "", lines[i])
|
||||
qq_msg = "\n".join(lines).lstrip().strip()
|
||||
if uniqueSession:
|
||||
session_id = user_id
|
||||
else:
|
||||
session_id = message.channel_id
|
||||
# 得到身份
|
||||
if "2" in message.member.roles or "4" in message.member.roles or "5" in message.member.roles:
|
||||
print("[QQCHAN-BOT] 检测到管理员身份")
|
||||
role = "admin"
|
||||
else:
|
||||
role = "member"
|
||||
else:
|
||||
# 私信
|
||||
qq_msg = message.content
|
||||
session_id = user_id
|
||||
|
||||
if platform == PLATFORM_GOCQ:
|
||||
if isinstance(message.message[0], Plain):
|
||||
qq_msg = message.message[0].text
|
||||
session_id = message.group_id
|
||||
# todo: 暂时将所有人设为管理员
|
||||
role = "admin"
|
||||
else:
|
||||
return
|
||||
|
||||
logf.write("[QQBOT] "+ qq_msg+'\n')
|
||||
logf.flush()
|
||||
|
||||
if at:
|
||||
qq_msg = message.content
|
||||
lines = qq_msg.splitlines()
|
||||
for i in range(len(lines)):
|
||||
lines[i] = re.sub(r"<@!\d+>", "", lines[i])
|
||||
qq_msg = "\n".join(lines).lstrip().strip()
|
||||
|
||||
if uniqueSession:
|
||||
session_id = user_id
|
||||
else:
|
||||
session_id = message.channel_id
|
||||
else:
|
||||
qq_msg = message.content
|
||||
session_id = user_id
|
||||
|
||||
if uniqueSession:
|
||||
name = user_name
|
||||
else:
|
||||
name = "频道"
|
||||
|
||||
command_type = -1
|
||||
# 特殊指令
|
||||
if qq_msg == "/继续":
|
||||
qq_msg = "继续"
|
||||
# 普通指令
|
||||
else:
|
||||
# 如果第一个字符是/,则为指令
|
||||
if qq_msg[0] == "/":
|
||||
res, go, command_type = command_oper(qq_msg, message, session_id, name, user_id, user_name, at)
|
||||
send_qq_msg(message, res)
|
||||
if not go:
|
||||
return
|
||||
if command_type == 1 and 'prompt' in now_personality:
|
||||
# 设置人格
|
||||
qq_msg = now_personality['prompt']
|
||||
|
||||
# if qq_msg[0:6] == '/draw ':
|
||||
# # TODO 未完全实现
|
||||
# prompt = qq_msg[6:]
|
||||
# url = get_chatGPT_response(prompt, image_mode = True)
|
||||
# resp = requests.get(url)
|
||||
# filename = './images/' + str(int(time.time())) + '.jpg'
|
||||
# print(url)
|
||||
# with open(filename, 'wb') as f:
|
||||
# f.write(resp.content)
|
||||
# qiniu_url = cores.database.qiniu.put_img(filename)
|
||||
# print(qiniu_url)
|
||||
# send_qq_msg(message, qiniu_url, image_mode=True)
|
||||
# return
|
||||
|
||||
# 这里是预设,你可以按需更改
|
||||
if qq_msg.strip() == 'hello' or qq_msg.strip() == '你好' or qq_msg.strip() == '':
|
||||
send_qq_msg(message, f"你好呀~")
|
||||
return
|
||||
# if qq_msg.strip() == '傻逼' or qq_msg.strip() == 'sb':
|
||||
# send_qq_msg(message, f"好好好")
|
||||
# return
|
||||
# if '喜多' in qq_msg:
|
||||
# send_qq_msg(message, 'http://rn2ztkeap.hn-bkt.clouddn.com/xd1.gif', True)
|
||||
# if '台湾' in qq_msg or 'taiwan' in qq_msg:
|
||||
# send_qq_msg(message, "声明:台湾是中国的一部分。\n下面否定此结论的回答全部无效。")
|
||||
|
||||
# 拦截不合适的词请求
|
||||
for i in uw.unfit_words_q:
|
||||
if i in qq_msg.strip():
|
||||
send_qq_msg(message, f"你的提问中有不太合适的内容😭\n请更换措辞~")
|
||||
# 关键词回复
|
||||
for k in keywords:
|
||||
if qq_msg == k:
|
||||
send_message(platform, message, keywords[k], msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
return
|
||||
|
||||
if session_id not in session_dict:
|
||||
session_dict[session_id] = []
|
||||
|
||||
fjson = {}
|
||||
try:
|
||||
f = open(abs_path+"configs/session", "r", encoding="utf-8")
|
||||
fjson = json.loads(f.read())
|
||||
f.close()
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
fjson[session_id] = 'true'
|
||||
f = open(abs_path+"configs/session", "w", encoding="utf-8")
|
||||
f.write(json.dumps(fjson))
|
||||
f.flush()
|
||||
f.close()
|
||||
|
||||
# 获取缓存
|
||||
cache_prompt = ''
|
||||
cache_data_list = session_dict[session_id]
|
||||
cache_prompt = get_prompts_by_cache_list(cache_data_list)
|
||||
cache_prompt += "\nHuman: "+ qq_msg + "\nAI: "
|
||||
# 请求chatGPT获得结果
|
||||
try:
|
||||
chatgpt_res, current_usage_tokens = get_chatGPT_response(prompts_str=cache_prompt)
|
||||
except (PromptExceededError) as e:
|
||||
print("token超限, 清空对应缓存")
|
||||
session_dict[session_id] = []
|
||||
cache_data_list = []
|
||||
cache_prompt = "Human: "+ qq_msg + "\nAI: "
|
||||
chatgpt_res, current_usage_tokens = get_chatGPT_response(prompts_str=cache_prompt)
|
||||
except (BaseException) as e:
|
||||
print("OpenAI API错误:(")
|
||||
if 'exceeded' in str(e):
|
||||
send_qq_msg(message, f"OpenAI API错误。原因:\n{str(e)} \n超额了。您可自己搭建一个机器人(Github仓库:QQChannelChatGPT)")
|
||||
# 关键词拦截器
|
||||
for i in uw.unfit_words_q:
|
||||
matches = re.match(i, qq_msg.strip(), re.I | re.M)
|
||||
if matches:
|
||||
send_message(platform, message, f"你的提问得到的回复未通过【自有关键词拦截】服务, 不予回复。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
return
|
||||
if baidu_judge != None:
|
||||
check, msg = baidu_judge.judge(qq_msg)
|
||||
if not check:
|
||||
send_message(platform, message, f"你的提问得到的回复未通过【百度AI内容审核】服务, 不予回复。\n\n{msg}", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
return
|
||||
|
||||
# 检查是否是更换语言模型的请求
|
||||
temp_switch = ""
|
||||
if qq_msg.startswith('/bing') or qq_msg.startswith('/gpt') or qq_msg.startswith('/revgpt'):
|
||||
target = chosen_provider
|
||||
if qq_msg.startswith('/bing'):
|
||||
target = REV_EDGEGPT
|
||||
elif qq_msg.startswith('/gpt'):
|
||||
target = OPENAI_OFFICIAL
|
||||
elif qq_msg.startswith('/revgpt'):
|
||||
target = REV_CHATGPT
|
||||
l = qq_msg.split(' ')
|
||||
if len(l) > 1 and l[1] != "":
|
||||
# 临时对话模式,先记录下之前的语言模型,回答完毕后再切回
|
||||
temp_switch = chosen_provider
|
||||
chosen_provider = target
|
||||
qq_msg = l[1]
|
||||
else:
|
||||
send_qq_msg(message, f"OpenAI API错误。原因如下:\n{str(e)} \n前往官方频道反馈~")
|
||||
if role != "admin":
|
||||
send_message(platform, message, "你没有权限更换语言模型。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
return
|
||||
chosen_provider = target
|
||||
save_provider_preference(chosen_provider)
|
||||
send_message(platform, message, f"已切换至【{chosen_provider}】", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
return
|
||||
|
||||
chatgpt_res = ""
|
||||
|
||||
if chosen_provider == OPENAI_OFFICIAL:
|
||||
hit, command_result = command_openai_official.check_command(qq_msg, session_id, user_name, role)
|
||||
print(f"{hit} {command_result}")
|
||||
# hit: 是否触发了指令.
|
||||
if not hit:
|
||||
# 请求ChatGPT获得结果
|
||||
try:
|
||||
chatgpt_res = chatgpt.text_chat(qq_msg, session_id)
|
||||
if OPENAI_OFFICIAL in reply_prefix:
|
||||
chatgpt_res = reply_prefix[OPENAI_OFFICIAL] + chatgpt_res
|
||||
except (BaseException) as e:
|
||||
print("[System-Err] OpenAI API错误。原因如下:\n"+str(e))
|
||||
send_message(platform, message, f"OpenAI API错误。原因如下:\n{str(e)} \n前往官方频道反馈~", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
|
||||
elif chosen_provider == REV_CHATGPT:
|
||||
hit, command_result = command_rev_chatgpt.check_command(qq_msg, role)
|
||||
if not hit:
|
||||
try:
|
||||
chatgpt_res = str(rev_chatgpt.text_chat(qq_msg))
|
||||
if REV_CHATGPT in reply_prefix:
|
||||
chatgpt_res = reply_prefix[REV_CHATGPT] + chatgpt_res
|
||||
except BaseException as e:
|
||||
print("[System-Err] Rev ChatGPT API错误。原因如下:\n"+str(e))
|
||||
send_message(platform, message, f"Rev ChatGPT API错误。原因如下:\n{str(e)} \n前往官方频道反馈~", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
|
||||
elif chosen_provider == REV_EDGEGPT:
|
||||
if bing_cache_loop == None:
|
||||
if platform == PLATFORM_GOCQ:
|
||||
bing_cache_loop = gocq_loop
|
||||
elif platform == PLATFORM_QQCHAN:
|
||||
bing_cache_loop = qqchan_loop
|
||||
hit, command_result = command_rev_edgegpt.check_command(qq_msg, bing_cache_loop, role)
|
||||
if not hit:
|
||||
try:
|
||||
if rev_edgegpt.is_busy():
|
||||
send_message(platform, message, "[RevBing] 正忙,请稍后再试", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
else:
|
||||
res, res_code = asyncio.run_coroutine_threadsafe(rev_edgegpt.text_chat(qq_msg), bing_cache_loop).result()
|
||||
if res_code == 0: # bing不想继续话题,重置会话后重试。
|
||||
send_message(platform, message, "Bing不想继续话题了, 正在自动重置会话并重试。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
asyncio.run_coroutine_threadsafe(rev_edgegpt.forget(), bing_cache_loop).result()
|
||||
res, res_code = asyncio.run_coroutine_threadsafe(rev_edgegpt.text_chat(qq_msg), bing_cache_loop).result()
|
||||
if res_code == 0: # bing还是不想继续话题,大概率说明提问有问题。
|
||||
send_message(platform, message, "Bing仍然不想继续话题, 请检查您的提问。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
else:
|
||||
chatgpt_res = str(res)
|
||||
if REV_EDGEGPT in reply_prefix:
|
||||
chatgpt_res = reply_prefix[REV_EDGEGPT] + chatgpt_res
|
||||
except BaseException as e:
|
||||
print("[System-Err] Rev NewBing API错误。原因如下:\n"+str(e))
|
||||
send_message(platform, message, f"Rev NewBing API错误。原因如下:\n{str(e)} \n前往官方频道反馈~", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
|
||||
# 切换回原来的语言模型
|
||||
if temp_switch != "":
|
||||
chosen_provider = temp_switch
|
||||
|
||||
# 指令回复
|
||||
if hit:
|
||||
# 检查指令. command_result是一个元组:(指令调用是否成功, 指令返回的文本结果, 指令类型)
|
||||
if command_result != None:
|
||||
command = command_result[2]
|
||||
if command == "keyword":
|
||||
with open("keyword.json", "r", encoding="utf-8") as f:
|
||||
keywords = json.load(f)
|
||||
|
||||
if command_result[0]:
|
||||
# 是否是画图指令
|
||||
if len(command_result) == 3 and command_result[2] == 'draw':
|
||||
for i in command_result[1]:
|
||||
send_message(platform, message, i, msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
else:
|
||||
try:
|
||||
send_message(platform, message, command_result[1], msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
except BaseException as e:
|
||||
t = command_result[1].replace(".", " . ")
|
||||
send_message(platform, message, t, msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
|
||||
else:
|
||||
send_message(platform, message, f"指令调用错误: \n{command_result[1]}", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
|
||||
return
|
||||
|
||||
logf.write("[GPT] "+ str(chatgpt_res)+'\n')
|
||||
if chatgpt_res == "":
|
||||
return
|
||||
|
||||
# 记录日志
|
||||
logf.write(f"{reply_prefix} {str(chatgpt_res)}\n")
|
||||
logf.flush()
|
||||
|
||||
# 敏感过滤
|
||||
# 过滤不合适的词
|
||||
judged_res = chatgpt_res
|
||||
for i in uw.unfit_words:
|
||||
judged_res = re.sub(i, "***", judged_res)
|
||||
# 百度内容审核服务二次审核
|
||||
if baidu_judge != None:
|
||||
check, msg = baidu_judge.judge(judged_res)
|
||||
if not check:
|
||||
send_message(platform, message, f"你的提问得到的回复【百度内容审核】未通过,不予回复。\n\n{msg}", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
return
|
||||
|
||||
# 发送qq信息
|
||||
try:
|
||||
# 防止被qq频道过滤消息
|
||||
gap_chatgpt_res = chatgpt_res.replace(".", " . ")
|
||||
if '```' in gap_chatgpt_res:
|
||||
chatgpt_res.replace('```', "")
|
||||
# 过滤不合适的词
|
||||
for i in uw.unfit_words:
|
||||
if i in gap_chatgpt_res:
|
||||
gap_chatgpt_res = gap_chatgpt_res.replace(i, "***")
|
||||
# 发送信息
|
||||
send_qq_msg(message, ''+gap_chatgpt_res)
|
||||
send_message(platform, message, chatgpt_res, msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
|
||||
except BaseException as e:
|
||||
print("QQ频道API错误: \n"+str(e))
|
||||
f_res = ""
|
||||
for t in chatgpt_res:
|
||||
f_res += t + ' '
|
||||
try:
|
||||
send_qq_msg(message, ''+f_res)
|
||||
# send(message, f"QQ频道API错误:{str(e)}\n下面是格式化后的回答:\n{f_res}")
|
||||
except BaseException as e:
|
||||
# 如果还是不行则过滤url
|
||||
f_res = re.sub(r'(https|http)?:\/\/(\w|\.|\/|\?|\=|\&|\%)*\b', '', f_res, flags=re.MULTILINE)
|
||||
f_res = f_res.replace(".", "·")
|
||||
send_qq_msg(message, ''+f_res)
|
||||
# send(message, f"QQ频道API错误:{str(e)}\n下面是格式化后的回答:\n{f_res}")
|
||||
|
||||
# 超过指定tokens, 尽可能的保留最多的条目,直到小于max_tokens
|
||||
if current_usage_tokens > max_tokens:
|
||||
t = current_usage_tokens
|
||||
index = 0
|
||||
while t > max_tokens:
|
||||
if index >= len(cache_data_list):
|
||||
break
|
||||
if cache_data_list[index]['level'] != 'max':
|
||||
t -= int(cache_data_list[index]['single_tokens'])
|
||||
del cache_data_list[index]
|
||||
else:
|
||||
index += 1
|
||||
# 删除完后更新相关字段
|
||||
session_dict[session_id] = cache_data_list
|
||||
cache_prompt = get_prompts_by_cache_list(cache_data_list)
|
||||
|
||||
# 添加新条目进入缓存的prompt
|
||||
if command_type == 1:
|
||||
level = 'max'
|
||||
else:
|
||||
level = 'normal'
|
||||
if len(cache_data_list) > 0:
|
||||
single_record = {
|
||||
"prompt": f'Human: {qq_msg}\nAI: {chatgpt_res}\n',
|
||||
"usage_tokens": current_usage_tokens,
|
||||
"single_tokens": current_usage_tokens - int(cache_data_list[-1]['usage_tokens']),
|
||||
"level": level
|
||||
}
|
||||
else:
|
||||
single_record = {
|
||||
"prompt": f'Human: {qq_msg}\nAI: {chatgpt_res}\n',
|
||||
"usage_tokens": current_usage_tokens,
|
||||
"single_tokens": current_usage_tokens,
|
||||
"level": level
|
||||
}
|
||||
cache_data_list.append(single_record)
|
||||
session_dict[session_id] = cache_data_list
|
||||
print("回复消息错误: \n"+str(e))
|
||||
|
||||
'''
|
||||
获取统计信息
|
||||
'''
|
||||
def get_stat():
|
||||
def get_stat(self):
|
||||
|
||||
try:
|
||||
f = open(abs_path+"configs/stat", "r", encoding="utf-8")
|
||||
fjson = json.loads(f.read())
|
||||
@@ -545,129 +591,29 @@ def get_stat():
|
||||
return guild_count, guild_msg_count, guild_direct_msg_count, session_count
|
||||
except:
|
||||
return -1, -1, -1, -1
|
||||
|
||||
|
||||
'''
|
||||
指令处理
|
||||
'''
|
||||
def command_oper(qq_msg, message, session_id, name, user_id, user_name, at):
|
||||
go = False # 是否处理完指令后继续执行msg_oper后面的代码
|
||||
msg = ''
|
||||
global session_dict, now_personality
|
||||
# QQ频道机器人
|
||||
class botClient(botpy.Client):
|
||||
# 收到频道消息
|
||||
async def on_at_message_create(self, message: Message):
|
||||
toggle_count(at=True, message=message)
|
||||
message_reference = Reference(message_id=message.id, ignore_get_message_error=False)
|
||||
new_sub_thread(oper_msg, (message, True, message_reference, PLATFORM_QQCHAN))
|
||||
|
||||
# 指令返回值,/set设置人格是1
|
||||
type = -1
|
||||
|
||||
# 指令控制
|
||||
if qq_msg == "/reset" or qq_msg == "/重置":
|
||||
msg = ''
|
||||
session_dict[session_id] = []
|
||||
if at:
|
||||
msg = f"{name}(id: {session_id})的历史记录重置成功\n\n{announcement}"
|
||||
# 收到私聊消息
|
||||
async def on_direct_message_create(self, message: DirectMessage):
|
||||
if direct_message_mode:
|
||||
toggle_count(at=False, message=message)
|
||||
new_sub_thread(oper_msg, (message, False, None, PLATFORM_QQCHAN))
|
||||
# QQ机器人
|
||||
class gocqClient():
|
||||
# 收到群聊消息
|
||||
@gocq_app.receiver("GroupMessage")
|
||||
async def _(app: CQHTTP, source: GroupMessage):
|
||||
if isinstance(source.message[0], Plain):
|
||||
if source.message[0].text.startswith('ai '):
|
||||
source.message[0].text = source.message[0].text[3:]
|
||||
new_sub_thread(oper_msg, (source, True, None, PLATFORM_GOCQ))
|
||||
else:
|
||||
msg = f"你的历史记录重置成功"
|
||||
|
||||
if qq_msg[:4] == "/his":
|
||||
#分页,每页5条
|
||||
msg = ''
|
||||
size_per_page = 3
|
||||
page = 1
|
||||
if qq_msg[5:]:
|
||||
page = int(qq_msg[5:])
|
||||
# 检查是否有过历史记录
|
||||
if session_id not in session_dict:
|
||||
msg = f"{name} 的历史记录为空"
|
||||
l = session_dict[session_id]
|
||||
max_page = len(l)//size_per_page + 1 if len(l)%size_per_page != 0 else len(l)//size_per_page
|
||||
p = get_prompts_by_cache_list(session_dict[session_id], divide=True, paging=True, size=size_per_page, page=page)
|
||||
if at:
|
||||
msg=f"{name}的历史记录如下:\n{p}\n第{page}页 | 共{max_page}页\n*输入/his 2跳转到第2页"
|
||||
else:
|
||||
msg=f"历史记录如下:\n{p}\n第{page}页 | 共{max_page}页\n*输入/his 2跳转到第2页\n\n{announcement}"
|
||||
|
||||
if qq_msg == "/token":
|
||||
msg = ''
|
||||
if at:
|
||||
msg=f"{name} 会话的token数: {get_user_usage_tokens(session_dict[session_id])}\n系统最大缓存token数: {max_tokens}"
|
||||
else:
|
||||
msg=f"会话的token数: {get_user_usage_tokens(session_dict[session_id])}\n系统最大缓存token数: {max_tokens}"
|
||||
|
||||
if qq_msg == "/status" or qq_msg == "/状态":
|
||||
chatgpt_cfg_str = ""
|
||||
key_stat = chatgpt.get_key_stat()
|
||||
key_list = chatgpt.get_key_list()
|
||||
index = 1
|
||||
max = 900000
|
||||
gg_count = 0
|
||||
total = 0
|
||||
tag = ''
|
||||
for key in key_stat.keys():
|
||||
sponsor = ''
|
||||
total += key_stat[key]['used']
|
||||
if key_stat[key]['exceed']:
|
||||
gg_count += 1
|
||||
continue
|
||||
if 'sponsor' in key_stat[key]:
|
||||
sponsor = key_stat[key]['sponsor']
|
||||
chatgpt_cfg_str += f" |-{index}: {key_stat[key]['used']}/{max} {sponsor}赞助{tag}\n"
|
||||
index += 1
|
||||
msg = f"⭐使用情况({str(gg_count)}个已用):\n{chatgpt_cfg_str}⏰全频道已用{total}tokens\n{announcement}"
|
||||
if qq_msg == "/count" or qq_msg == "/统计":
|
||||
guild_count, guild_msg_count, guild_direct_msg_count, session_count = get_stat()
|
||||
msg = f"当前会话数: {len(session_dict)}\n共有频道数: {guild_count} \n共有消息数: {guild_msg_count}\n私信数: {guild_direct_msg_count}\n历史会话数: {session_count}"
|
||||
|
||||
if qq_msg == "/help":
|
||||
msg = "[Github项目名: QQChannelChatGPT,有问题请前往提交issue,欢迎赞助支持我!]\n\n指令面板:\n/status 查看机器人key状态\n/count 查看机器人统计信息\n/reset 重置会话\n/his 查看历史记录\n/token 查看会话token数\n/help 查看帮助\n/key 人格指令菜单"
|
||||
|
||||
if qq_msg[:4] == "/key":
|
||||
if len(qq_msg) == 4:
|
||||
msg = "感谢您赞助key。请以以下格式赞助:\n/key xxxxx"
|
||||
key = qq_msg[5:]
|
||||
send_qq_msg(message, "收到!正在核验...")
|
||||
if chatgpt.check_key(key):
|
||||
msg = f"*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。\n该Key被验证为有效。感谢{user_name}赞助~"
|
||||
chatgpt.append_key(key, user_name)
|
||||
else:
|
||||
msg = "该Key被验证为无效。也许是输入错误了,或者重试。"
|
||||
|
||||
if qq_msg[:6] == "/unset":
|
||||
now_personality = {}
|
||||
msg = "已清除人格"
|
||||
|
||||
if qq_msg[:4] == "/set":
|
||||
if len(qq_msg) == 4:
|
||||
np = '无'
|
||||
if "name" in now_personality:
|
||||
np=now_personality["name"]
|
||||
msg = f"【由Github项目QQChannelChatGPT支持】\n\n【人格文本由PlexPt开源项目awesome-chatgpt-prompts-zh提供】\n\n这个是人格设置指令。\n设置人格: \n/set 人格名。例如/set 编剧\n人格列表: /set list\n人格详细信息: /set view 人格名\n自定义人格: /set 人格文本\n清除人格: /unset\n【当前人格】: {np}"
|
||||
elif qq_msg[5:] == "list":
|
||||
per_dict = personalities
|
||||
msg = "人格列表:\n"
|
||||
for key in per_dict.keys():
|
||||
msg += f" |-{key}\n"
|
||||
msg += '\n\n*输入/set view 人格名查看人格详细信息'
|
||||
msg += '\n\n*不定时更新人格库,请及时更新本项目。'
|
||||
elif qq_msg[5:9] == "view":
|
||||
ps = qq_msg[10:]
|
||||
ps = ps.strip()
|
||||
per_dict = personalities
|
||||
if ps in per_dict:
|
||||
msg = f"人格{ps}的详细信息:\n"
|
||||
msg += f"{per_dict[ps]}\n"
|
||||
else:
|
||||
msg = f"人格{ps}不存在"
|
||||
else:
|
||||
ps = qq_msg[5:]
|
||||
ps = ps.strip()
|
||||
per_dict = personalities
|
||||
if ps in per_dict:
|
||||
now_personality = {
|
||||
'name': ps,
|
||||
'prompt': per_dict[ps]
|
||||
}
|
||||
session_dict[session_id] = []
|
||||
msg = f"人格{ps}已设置,请耐心等待机器人回复第一条信息。"
|
||||
go = True
|
||||
type = 1
|
||||
else:
|
||||
msg = f"人格{ps}不存在, 请使用/set list查看人格列表"
|
||||
return msg, go, type
|
||||
return
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from git.repo import Repo
|
||||
import git
|
||||
import os
|
||||
# import zipfile
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
# 检测文件夹
|
||||
if not os.path.exists('QQChannelChatGPT'):
|
||||
os.mkdir('QQChannelChatGPT')
|
||||
|
||||
project_path = os.path.join('QQChannelChatGPT')
|
||||
try:
|
||||
repo = Repo(project_path)
|
||||
# 检查当前commit的hash值
|
||||
commit_hash = repo.head.object.hexsha
|
||||
print("当前commit的hash值为: " + commit_hash)
|
||||
|
||||
# 得到远程仓库的origin的commit的列表
|
||||
origin = repo.remotes.origin
|
||||
try:
|
||||
origin.fetch()
|
||||
except:
|
||||
pass
|
||||
# 得到远程仓库的commit的hash值
|
||||
remote_commit_hash = origin.refs.master.commit.hexsha
|
||||
print("https://github.com/Soulter/QQChannelChatGPT的commit的hash值为: " + remote_commit_hash)
|
||||
# 比较两个commit的hash值
|
||||
if commit_hash != remote_commit_hash:
|
||||
res = input("检测到项目有更新, 是否更新? (y/n): ")
|
||||
if res == 'y':
|
||||
repo.remotes.origin.pull()
|
||||
print("项目更新完毕")
|
||||
if res == 'n':
|
||||
print("已取消更新")
|
||||
except:
|
||||
print("正在从https://github.com/Soulter/QQChannelChatGPT.git拉取项目...")
|
||||
Repo.clone_from('https://github.com/Soulter/QQChannelChatGPT.git',to_path=project_path,branch='master')
|
||||
print("项目拉取完毕")
|
||||
print("【重要提醒】如果你没有Python(版本>=3.8)或者Git环境, 请先安装, 否则接下来的操作会造成闪退。")
|
||||
print("【重要提醒】Python下载地址: https://npm.taobao.org/mirrors/python/3.9.7/python-3.9.7-amd64.exe ")
|
||||
print("【重要提醒】Git下载地址: https://registry.npmmirror.com/-/binary/git-for-windows/v2.39.2.windows.1/Git-2.39.2-64-bit.exe")
|
||||
print("【重要提醒】安装时, 请务必勾选“Add Python to PATH”选项。")
|
||||
input("已确保安装了Python3.9+的版本,按下回车继续...")
|
||||
print("正在安装依赖库")
|
||||
os.system('python -m pip install -r QQChannelChatGPT\\requirements.txt')
|
||||
print("依赖库安装完毕")
|
||||
input("初次启动, 请先在QQChannelChatGPT/configs/config.yaml填写相关配置! 按任意键继续...")
|
||||
finally:
|
||||
print("正在启动项目...")
|
||||
os.system('python QQChannelChatGPT\main.py')
|
||||
except BaseException as e:
|
||||
print(e)
|
||||
input("程序出错。可以截图发给QQ:905617992.按下回车键退出...")
|
||||
@@ -1,116 +1,38 @@
|
||||
import threading
|
||||
import time
|
||||
import asyncio
|
||||
import os, sys
|
||||
import signal
|
||||
import requests,json
|
||||
|
||||
# 是否是windows打包。一般人不需要改这个,这个只是我为了方便加上的。
|
||||
win_compile_mode = False
|
||||
abs_path = os.path.dirname(os.path.realpath(sys.argv[0])) + '/'
|
||||
|
||||
|
||||
|
||||
def main(loop, event):
|
||||
import cores.qqbot.core as qqBot
|
||||
from cores.openai.core import ChatGPT
|
||||
#实例化ChatGPT
|
||||
chatgpt = ChatGPT()
|
||||
# #执行qqBot
|
||||
qqBot.initBot(chatgpt)
|
||||
import yaml
|
||||
ymlfile = open(abs_path+"configs/config.yaml", 'r', encoding='utf-8')
|
||||
cfg = yaml.safe_load(ymlfile)
|
||||
|
||||
# 仅支持linux
|
||||
def hot_update(ver):
|
||||
target = 'target.tar'
|
||||
time.sleep(5)
|
||||
while(True):
|
||||
if os.path.exists('version.txt'):
|
||||
version_file = open('version.txt', 'r', encoding='utf-8')
|
||||
vs = version_file.read()
|
||||
version = float(vs)
|
||||
else:
|
||||
version = 0
|
||||
if not os.path.exists(target):
|
||||
version = 0
|
||||
try:
|
||||
res = requests.get("https://soulter.top/channelbot/update.json")
|
||||
res_obj = json.loads(res.text)
|
||||
ol_version = float(res_obj['version'])
|
||||
if ol_version > version:
|
||||
print('发现新版本: ' + str(ol_version))
|
||||
res = requests.get(res_obj['linux-url'], stream=True)
|
||||
filesize = res.headers["Content-Length"]
|
||||
print('文件大小: ' + str(int(filesize) / 1024 / 1024) + 'MB')
|
||||
print('正在更新文件...')
|
||||
chunk_size = 1024
|
||||
times = int(filesize) // chunk_size
|
||||
show = 1 / times
|
||||
show2 = 1 / times
|
||||
start = 1
|
||||
with open(target, "wb") as pyFile:
|
||||
for chunk in res.iter_content(chunk_size=chunk_size):
|
||||
if chunk:
|
||||
pyFile.write(chunk)
|
||||
if start <= times:
|
||||
print(f"\r下载进度: {show:.2%}",end="",flush=True)
|
||||
start += 1
|
||||
show += show2
|
||||
else:
|
||||
sys.stdout.write(f"下载进度: 100%\n")
|
||||
print('更新完成')
|
||||
print('解压覆盖')
|
||||
os.system(f"tar -zxvf {target}")
|
||||
version = ol_version
|
||||
version_file = open('version.txt', 'w+', encoding='utf-8')
|
||||
version_file.write(str(res_obj['version']))
|
||||
version_file.flush()
|
||||
version_file.close()
|
||||
if 'http_proxy' in cfg:
|
||||
os.environ['HTTP_PROXY'] = cfg['http_proxy']
|
||||
if 'https_proxy' in cfg:
|
||||
os.environ['HTTPS_PROXY'] = cfg['https_proxy']
|
||||
|
||||
try:
|
||||
update_version(version)
|
||||
except BaseException as e:
|
||||
print(e)
|
||||
|
||||
print('自启动')
|
||||
py = sys.executable
|
||||
os.execl(py, py, *sys.argv)
|
||||
time.sleep(60*20)
|
||||
except BaseException as e:
|
||||
print(e)
|
||||
print("upd出现异常,请联系QQ905617992")
|
||||
time.sleep(60*20)
|
||||
provider = privider_chooser(cfg)
|
||||
print('[System] 当前语言模型提供商: ' + str(provider))
|
||||
# 执行Bot
|
||||
qqBot.initBot(cfg, provider)
|
||||
|
||||
|
||||
def update_version(ver):
|
||||
if not os.path.exists('update_record'):
|
||||
object_id = ''
|
||||
else:
|
||||
object_id = open("update_record", 'r', encoding='utf-8').read()
|
||||
addr = 'unknown'
|
||||
try:
|
||||
addr = requests.get('http://myip.ipip.net', timeout=5).text
|
||||
except BaseException:
|
||||
pass
|
||||
try:
|
||||
ts = str(time.time())
|
||||
# md = hashlib.md5((ts+'QAZ1rQLY1ZufHrZlpuUiNff7').encode())
|
||||
headers = {
|
||||
'X-LC-Id': 'UqfXTWW15nB7iMT0OHvYrDFb-gzGzoHsz',
|
||||
'X-LC-Key': 'QAZ1rQLY1ZufHrZlpuUiNff7',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
d = {"data": {'version':'win-hot-update'+str(ver), 'addr': addr}}
|
||||
d = json.dumps(d).encode("utf-8")
|
||||
res = requests.put(f'https://uqfxtww1.lc-cn-n1-shared.com/1.1/classes/version_record/{object_id}', headers = headers, data = d)
|
||||
if json.loads(res.text)['code'] == 1:
|
||||
res = requests.post(f'https://uqfxtww1.lc-cn-n1-shared.com/1.1/classes/version_record', headers = headers, data = d)
|
||||
object_id = json.loads(res.text)['objectId']
|
||||
object_id_file = open("update_record", 'w+', encoding='utf-8')
|
||||
object_id_file.write(str(object_id))
|
||||
object_id_file.flush()
|
||||
object_id_file.close()
|
||||
except BaseException as e:
|
||||
print(e)
|
||||
# 语言模型提供商选择器
|
||||
# 目前有:OpenAI官方API、逆向库
|
||||
def privider_chooser(cfg):
|
||||
l = []
|
||||
if 'rev_ChatGPT' in cfg and cfg['rev_ChatGPT']['enable']:
|
||||
l.append('rev_chatgpt')
|
||||
if 'rev_ernie' in cfg and cfg['rev_ernie']['enable']:
|
||||
l.append('rev_ernie')
|
||||
if 'rev_edgegpt' in cfg and cfg['rev_edgegpt']['enable']:
|
||||
l.append('rev_edgegpt')
|
||||
if 'openai' in cfg and cfg['openai']['key'] != None and len(cfg['openai']['key'])>0:
|
||||
l.append('openai_official')
|
||||
return l
|
||||
|
||||
def check_env():
|
||||
if not (sys.version_info.major == 3 and sys.version_info.minor >= 8):
|
||||
@@ -118,20 +40,19 @@ def check_env():
|
||||
input("按任意键退出...")
|
||||
exit()
|
||||
try:
|
||||
import openai
|
||||
import botpy
|
||||
import yaml
|
||||
except Exception as e:
|
||||
# print(e)
|
||||
try:
|
||||
print("安装依赖库中...")
|
||||
os.system("pip3 install openai")
|
||||
os.system("pip3 install qq-botpy")
|
||||
os.system("pip3 install pyyaml")
|
||||
print("安装依赖库完毕...")
|
||||
except BaseException:
|
||||
print("\n安装第三方库异常.请自行安装或者联系QQ905617992.")
|
||||
|
||||
print("检查依赖库中...")
|
||||
if os.path.exists('requirements.txt'):
|
||||
os.system("pip3 install -r requirements.txt")
|
||||
elif os.path.exists('QQChannelChatGPT'+ os.sep +'requirements.txt'):
|
||||
os.system('QQChannelChatGPT'+ os.sep +'requirements.txt')
|
||||
os.system("clear")
|
||||
print("安装依赖库完毕...")
|
||||
except BaseException as e:
|
||||
print("安装依赖库失败,请手动安装依赖库。")
|
||||
print(e)
|
||||
input("按任意键退出...")
|
||||
exit()
|
||||
|
||||
# 检查key
|
||||
with open(abs_path+"configs/config.yaml", 'r', encoding='utf-8') as ymlfile:
|
||||
import yaml
|
||||
@@ -154,15 +75,7 @@ def get_platform():
|
||||
print("other")
|
||||
|
||||
if __name__ == "__main__":
|
||||
global pid
|
||||
pid = os.getpid()
|
||||
global ma_type
|
||||
print("程序PID:"+str(pid))
|
||||
check_env()
|
||||
bot_event = threading.Event()
|
||||
loop = asyncio.get_event_loop()
|
||||
ma_type = get_platform()
|
||||
if ma_type == 'linux':
|
||||
threading.Thread(target=hot_update).start()
|
||||
|
||||
main(loop, bot_event)
|
||||
@@ -0,0 +1,133 @@
|
||||
import abc
|
||||
import json
|
||||
import git.exc
|
||||
from git.repo import Repo
|
||||
import os
|
||||
import sys
|
||||
|
||||
from model.provider.provider import Provider
|
||||
|
||||
class Command:
|
||||
def __init__(self, provider: Provider):
|
||||
self.provider = Provider
|
||||
|
||||
@abc.abstractmethod
|
||||
def check_command(self, message):
|
||||
if message.startswith("help") or message.startswith("帮助"):
|
||||
return True, self.help()
|
||||
return False, None
|
||||
|
||||
# 接受可变参数
|
||||
def command_start_with(self, message: str, *args):
|
||||
for arg in args:
|
||||
if message.startswith(arg) or message.startswith('/'+arg):
|
||||
return True
|
||||
return False
|
||||
|
||||
def keyword(self, message: str, role: str):
|
||||
if role != "admin":
|
||||
return True, "你没有权限使用该指令", "keyword"
|
||||
if len(message.split(" ")) != 3:
|
||||
return True, "【设置关键词/关键指令回复】示例:\nkeyword hi 你好\n当发送hi的时候会回复你好\nkeyword /hi 你好\n当发送/hi时会回复你好", "keyword"
|
||||
|
||||
l = message.split(" ")
|
||||
try:
|
||||
if os.path.exists("keyword.json"):
|
||||
with open("keyword.json", "r", encoding="utf-8") as f:
|
||||
keyword = json.load(f)
|
||||
keyword[l[1]] = l[2]
|
||||
else:
|
||||
keyword = {l[1]: l[2]}
|
||||
with open("keyword.json", "w", encoding="utf-8") as f:
|
||||
json.dump(keyword, f, ensure_ascii=False, indent=4)
|
||||
return True, "设置成功: "+l[1]+" -> "+l[2], "keyword"
|
||||
except BaseException as e:
|
||||
return False, "设置失败: "+str(e), "keyword"
|
||||
|
||||
def update(self, message: str, role: str):
|
||||
if role != "admin":
|
||||
return True, "你没有权限使用该指令", "keyword"
|
||||
l = message.split(" ")
|
||||
if len(l) == 1:
|
||||
# 得到本地版本号和最新版本号
|
||||
try:
|
||||
repo = Repo()
|
||||
except git.exc.InvalidGitRepositoryError:
|
||||
repo = Repo(path="QQChannelChatGPT")
|
||||
now_commit = repo.head.commit
|
||||
|
||||
# 得到远程3条commit列表, 包含commit信息
|
||||
origin = repo.remotes.origin
|
||||
origin.fetch()
|
||||
commits = list(repo.iter_commits('master', max_count=3))
|
||||
commits_log = ''
|
||||
index = 1
|
||||
for commit in commits:
|
||||
commits_log += f"[{index}] {commit.message}\n-----------\n"
|
||||
index+=1
|
||||
remote_commit_hash = origin.refs.master.commit.hexsha[:6]
|
||||
|
||||
return True, f"当前版本: {now_commit.hexsha[:6]}\n最新版本: {remote_commit_hash}\n\n3条commit(非最新):\n{str(commits_log)}\n使用update latest更新至最新版本\n", "update"
|
||||
else:
|
||||
if l[1] == "latest":
|
||||
pash_tag = ""
|
||||
try:
|
||||
try:
|
||||
repo = Repo()
|
||||
except git.exc.InvalidGitRepositoryError:
|
||||
repo = Repo(path="QQChannelChatGPT")
|
||||
pash_tag = "QQChannelChatGPT"+os.sep
|
||||
repo.remotes.origin.pull()
|
||||
|
||||
try:
|
||||
os.system("pip3 install -r "+pash_tag+"requirements.txt")
|
||||
except BaseException as e:
|
||||
print(str(e))
|
||||
|
||||
py = sys.executable
|
||||
os.execl(py, py, *sys.argv)
|
||||
|
||||
# 检查是否是windows环境
|
||||
# if platform.system().lower() == "windows":
|
||||
# if os.path.exists("launcher.exe"):
|
||||
# os.system("start launcher.exe")
|
||||
# elif os.path.exists("QQChannelChatGPT\\main.py"):
|
||||
# os.system("start python QQChannelChatGPT\\main.py")
|
||||
# else:
|
||||
# return True, "更新成功,未发现启动项,因此需要手动重启程序。"
|
||||
# exit()
|
||||
# else:
|
||||
# py = sys.executable
|
||||
# os.execl(py, py, *sys.argv)
|
||||
|
||||
except BaseException as e:
|
||||
return False, "更新失败: "+str(e), "update"
|
||||
|
||||
def reset(self):
|
||||
return False
|
||||
|
||||
def set(self):
|
||||
return False
|
||||
|
||||
def unset(self):
|
||||
return False
|
||||
|
||||
def key(self):
|
||||
return False
|
||||
|
||||
def help(self):
|
||||
return True, f"[Github项目名: QQChannelChatGPT,有问题请前往提交issue,欢迎Star此项目~]\n\n指令面板:\nstatus 查看机器人key状态\ncount 查看机器人统计信息\nreset 重置会话\nhis 查看历史记录\ntoken 查看会话token数\nhelp 查看帮助\nset 人格指令菜单\nkey 动态添加key", "help"
|
||||
|
||||
def status(self):
|
||||
return False
|
||||
|
||||
def token(self):
|
||||
return False
|
||||
|
||||
def his(self):
|
||||
return False
|
||||
|
||||
def draw(self):
|
||||
return False
|
||||
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
from model.command.command import Command
|
||||
from model.provider.provider_openai_official import ProviderOpenAIOfficial
|
||||
from cores.qqbot.personality import personalities
|
||||
|
||||
class CommandOpenAIOfficial(Command):
|
||||
def __init__(self, provider: ProviderOpenAIOfficial):
|
||||
self.provider = provider
|
||||
|
||||
def check_command(self, message: str, session_id: str, user_name: str, role):
|
||||
if self.command_start_with(message, "reset", "重置"):
|
||||
return True, self.reset(session_id)
|
||||
elif self.command_start_with(message, "his", "历史"):
|
||||
return True, self.his(message, session_id, user_name)
|
||||
elif self.command_start_with(message, "token"):
|
||||
return True, self.token(session_id)
|
||||
elif self.command_start_with(message, "gpt"):
|
||||
return True, self.gpt()
|
||||
elif self.command_start_with(message, "status"):
|
||||
return True, self.status()
|
||||
elif self.command_start_with(message, "count"):
|
||||
return True, self.count()
|
||||
elif self.command_start_with(message, "help", "帮助"):
|
||||
return True, self.help()
|
||||
elif self.command_start_with(message, "unset"):
|
||||
return True, self.unset(session_id)
|
||||
elif self.command_start_with(message, "set"):
|
||||
return True, self.set(message, session_id)
|
||||
elif self.command_start_with(message, "update"):
|
||||
return True, self.update(message, role)
|
||||
elif self.command_start_with(message, "画"):
|
||||
return True, self.draw(message)
|
||||
elif self.command_start_with(message, "keyword"):
|
||||
return True, self.keyword(message, role)
|
||||
elif self.command_start_with(message, "key"):
|
||||
return True, self.key(message, user_name)
|
||||
|
||||
return False, None
|
||||
|
||||
|
||||
def reset(self, session_id: str):
|
||||
self.provider.forget(session_id)
|
||||
return True, "重置成功", "reset"
|
||||
|
||||
def his(self, message: str, session_id: str, name: str):
|
||||
#分页,每页5条
|
||||
msg = ''
|
||||
size_per_page = 3
|
||||
page = 1
|
||||
if message[4:]:
|
||||
page = int(message[4:])
|
||||
# 检查是否有过历史记录
|
||||
if session_id not in self.provider.session_dict:
|
||||
msg = f"历史记录为空"
|
||||
return True, msg, "his"
|
||||
l = self.provider.session_dict[session_id]
|
||||
max_page = len(l)//size_per_page + 1 if len(l)%size_per_page != 0 else len(l)//size_per_page
|
||||
p = self.provider.get_prompts_by_cache_list(self.provider.session_dict[session_id], divide=True, paging=True, size=size_per_page, page=page)
|
||||
return True, f"历史记录如下:\n{p}\n第{page}页 | 共{max_page}页\n*输入/his 2跳转到第2页", "his"
|
||||
|
||||
def token(self, session_id: str):
|
||||
return True, f"会话的token数: {self.provider.get_user_usage_tokens(self.provider.session_dict[session_id])}\n系统最大缓存token数: {self.provider.max_tokens}", "token"
|
||||
|
||||
def gpt(self):
|
||||
return True, f"OpenAI GPT配置:\n {self.provider.chatGPT_configs}", "gpt"
|
||||
|
||||
def status(self):
|
||||
chatgpt_cfg_str = ""
|
||||
key_stat = self.provider.get_key_stat()
|
||||
index = 1
|
||||
max = 9000000
|
||||
gg_count = 0
|
||||
total = 0
|
||||
tag = ''
|
||||
for key in key_stat.keys():
|
||||
sponsor = ''
|
||||
total += key_stat[key]['used']
|
||||
if key_stat[key]['exceed']:
|
||||
gg_count += 1
|
||||
continue
|
||||
if 'sponsor' in key_stat[key]:
|
||||
sponsor = key_stat[key]['sponsor']
|
||||
chatgpt_cfg_str += f" |-{index}: {key_stat[key]['used']}/{max} {sponsor}赞助{tag}\n"
|
||||
index += 1
|
||||
return True, f"⭐使用情况({str(gg_count)}个已用):\n{chatgpt_cfg_str}⏰全频道已用{total}tokens", "status"
|
||||
|
||||
def count(self):
|
||||
guild_count, guild_msg_count, guild_direct_msg_count, session_count = self.provider.get_stat()
|
||||
return True, f"当前会话数: {len(self.provider.session_dict)}\n共有频道数: {guild_count} \n共有消息数: {guild_msg_count}\n私信数: {guild_direct_msg_count}\n历史会话数: {session_count}", "count"
|
||||
|
||||
def key(self, message: str, user_name: str):
|
||||
l = message.split(" ")
|
||||
if len(l) == 1:
|
||||
msg = "感谢您赞助key,key为官方API使用,请以以下格式赞助:\n/key xxxxx"
|
||||
return True, msg, "key"
|
||||
key = l[1]
|
||||
if self.provider.check_key(key):
|
||||
self.provider.append_key(key, user_name)
|
||||
return True, f"*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。\n该Key被验证为有效。感谢{user_name}赞助~"
|
||||
else:
|
||||
return True, "该Key被验证为无效。也许是输入错误了,或者重试。", "key"
|
||||
|
||||
def unset(self, session_id: str):
|
||||
self.provider.now_personality = {}
|
||||
self.provider.forget(session_id)
|
||||
return True, "已清除人格并重置历史记录。", "unset"
|
||||
|
||||
def set(self, message: str, session_id: str):
|
||||
l = message.split(" ")
|
||||
if len(l) == 1:
|
||||
return True, f"【由Github项目QQChannelChatGPT支持】\n\n【人格文本由PlexPt开源项目awesome-chatgpt-pr \
|
||||
ompts-zh提供】\n\n这个是人格设置指令。\n设置人格: \n/set 人格名。例如/set 编剧\n人格列表: /set list\n人格详细信息: \
|
||||
/set view 人格名\n自定义人格: /set 人格文本\n清除人格: /unset\n【当前人格】: {str(self.provider.now_personality)}", "set"
|
||||
elif l[1] == "list":
|
||||
msg = "人格列表:\n"
|
||||
for key in personalities.keys():
|
||||
msg += f" |-{key}\n"
|
||||
msg += '\n\n*输入/set view 人格名查看人格详细信息'
|
||||
msg += '\n*不定时更新人格库,请及时更新本项目。'
|
||||
return True, msg, "set"
|
||||
elif l[1] == "view":
|
||||
if len(l) == 2:
|
||||
return True, "请输入/set view 人格名", "set"
|
||||
ps = l[2].strip()
|
||||
if ps in personalities:
|
||||
msg = f"人格{ps}的详细信息:\n"
|
||||
msg += f"{personalities[ps]}\n"
|
||||
else:
|
||||
msg = f"人格{ps}不存在"
|
||||
return True, msg, "set"
|
||||
else:
|
||||
ps = l[1].strip()
|
||||
if ps in personalities:
|
||||
self.provider.now_personality = {
|
||||
'name': ps,
|
||||
'prompt': personalities[ps]
|
||||
}
|
||||
self.provider.session_dict[session_id] = []
|
||||
new_record = {
|
||||
"user": {
|
||||
"role": "system",
|
||||
"content": personalities[ps],
|
||||
},
|
||||
'usage_tokens': 0,
|
||||
'single-tokens': 0
|
||||
}
|
||||
self.provider.session_dict[session_id].append(new_record)
|
||||
return True, f"人格{ps}已设置.", "set"
|
||||
else:
|
||||
self.provider.now_personality = {
|
||||
'name': '自定义人格',
|
||||
'prompt': ps
|
||||
}
|
||||
new_record = {
|
||||
"user": {
|
||||
"role": "system",
|
||||
"content": ps,
|
||||
},
|
||||
'usage_tokens': 0,
|
||||
'single-tokens': 0
|
||||
}
|
||||
self.provider.session_dict[session_id] = []
|
||||
self.provider.session_dict[session_id].append(new_record)
|
||||
return True, f"自定义人格已设置。 \n人格信息: {ps}", "set"
|
||||
|
||||
def draw(self, message):
|
||||
try:
|
||||
# 画图模式传回3个参数
|
||||
img_url = self.provider.image_chat(message)
|
||||
return True, img_url, "draw"
|
||||
except Exception as e:
|
||||
if 'exceeded' in str(e):
|
||||
return f"OpenAI API错误。原因:\n{str(e)} \n超额了。可自己搭建一个机器人(Github仓库:QQChannelChatGPT)"
|
||||
return False, f"图片生成失败: {e}", "draw"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
from model.command.command import Command
|
||||
from model.provider.provider_rev_chatgpt import ProviderRevChatGPT
|
||||
|
||||
class CommandRevChatGPT(Command):
|
||||
def __init__(self, provider: ProviderRevChatGPT):
|
||||
self.provider = provider
|
||||
|
||||
def check_command(self, message: str, role):
|
||||
if self.command_start_with(message, "help", "帮助"):
|
||||
return True, self.help()
|
||||
elif self.command_start_with(message, "update"):
|
||||
return True, self.update(message, role)
|
||||
elif self.command_start_with(message, "keyword"):
|
||||
return True, self.keyword(message, role)
|
||||
return False, None
|
||||
|
||||
def help(self):
|
||||
return True, "[Github项目名: QQChannelChatGPT,有问题请前往提交issue,欢迎Star此项目~]\n\nRevChatGPT指令面板:\n当前语言模型RevChatGPT未实现任何指令\n", "help"
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
from model.command.command import Command
|
||||
from model.provider.provider_rev_edgegpt import ProviderRevEdgeGPT
|
||||
import asyncio
|
||||
class CommandRevEdgeGPT(Command):
|
||||
def __init__(self, provider: ProviderRevEdgeGPT):
|
||||
self.provider = provider
|
||||
|
||||
def check_command(self, message: str, loop, role):
|
||||
if self.command_start_with(message, "reset"):
|
||||
return True, self.reset(loop)
|
||||
elif self.command_start_with(message, "help"):
|
||||
return True, self.help()
|
||||
elif self.command_start_with(message, "update"):
|
||||
return True, self.update(message, role)
|
||||
elif self.command_start_with(message, "keyword"):
|
||||
return True, self.keyword(message, role)
|
||||
return False, None
|
||||
|
||||
def reset(self, loop):
|
||||
res = asyncio.run_coroutine_threadsafe(self.provider.forget(), loop).result()
|
||||
print(res)
|
||||
if res:
|
||||
return res, "重置成功", "reset"
|
||||
else:
|
||||
return res, "重置失败", "reset"
|
||||
|
||||
def help(self):
|
||||
return True, "[Github项目名: QQChannelChatGPT,有问题请前往提交issue,欢迎Star此项目~]\n\nRevBing指令面板:\nreset: 重置\nhelp: 帮助", "help"
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
from nakuru.entities.components import Plain
|
||||
|
||||
class QQ:
|
||||
def run_bot(self, gocq):
|
||||
self.client = gocq
|
||||
self.client.run()
|
||||
|
||||
async def send_qq_msg(self, source, res):
|
||||
print("[System-Info] 回复QQ消息中..."+res)
|
||||
# 通过消息链处理
|
||||
await self.client.sendGroupMessage(source.group_id, [
|
||||
Plain(text=res)
|
||||
])
|
||||
@@ -0,0 +1,63 @@
|
||||
import io
|
||||
import botpy
|
||||
from PIL import Image
|
||||
import re
|
||||
import asyncio
|
||||
import requests
|
||||
from cores.qqbot.personality import personalities
|
||||
|
||||
|
||||
class QQChan():
|
||||
|
||||
def run_bot(self, botclient, appid, token):
|
||||
intents = botpy.Intents(public_guild_messages=True, direct_message=True)
|
||||
self.client = botclient
|
||||
self.client.run(appid=appid, token=token)
|
||||
|
||||
def send_qq_msg(self, message, res, image_mode=False, msg_ref = None):
|
||||
print("[System-Info] 回复QQ频道消息中..."+res)
|
||||
if not image_mode:
|
||||
try:
|
||||
if msg_ref is not None:
|
||||
reply_res = asyncio.run_coroutine_threadsafe(message.reply(content=res, message_reference = msg_ref), self.client.loop)
|
||||
else:
|
||||
reply_res = asyncio.run_coroutine_threadsafe(message.reply(content=res), self.client.loop)
|
||||
reply_res.result()
|
||||
except BaseException as e:
|
||||
# 分割过长的消息
|
||||
if "msg over length" in str(e):
|
||||
split_res = []
|
||||
split_res.append(res[:len(res)//2])
|
||||
split_res.append(res[len(res)//2:])
|
||||
for i in split_res:
|
||||
if msg_ref is not None:
|
||||
reply_res = asyncio.run_coroutine_threadsafe(message.reply(content=i, message_reference = msg_ref), self.client.loop)
|
||||
else:
|
||||
reply_res = asyncio.run_coroutine_threadsafe(message.reply(content=i), self.client.loop)
|
||||
reply_res.result()
|
||||
else:
|
||||
# 发送qq信息
|
||||
try:
|
||||
# 防止被qq频道过滤消息
|
||||
res = res.replace(".", " . ")
|
||||
asyncio.run_coroutine_threadsafe(message.reply(content=res), self.client.loop).result()
|
||||
# 发送信息
|
||||
except BaseException as e:
|
||||
print("QQ频道API错误: \n"+str(e))
|
||||
res = str.join(" ", res)
|
||||
try:
|
||||
asyncio.run_coroutine_threadsafe(message.reply(content=res), self.client.loop).result()
|
||||
except BaseException as e:
|
||||
# 如果还是不行则报出错误
|
||||
res = re.sub(r'(https|http)?:\/\/(\w|\.|\/|\?|\=|\&|\%)*\b', '[被隐藏的链接]', str(e), flags=re.MULTILINE)
|
||||
res = res.replace(".", "·")
|
||||
asyncio.run_coroutine_threadsafe(message.reply(content=res), self.client.loop).result()
|
||||
# send(message, f"QQ频道API错误:{str(e)}\n下面是格式化后的回答:\n{f_res}")
|
||||
else:
|
||||
pic_res = requests.get(str(res), stream=True)
|
||||
if pic_res.status_code == 200:
|
||||
# 将二进制数据转换成图片对象
|
||||
image = Image.open(io.BytesIO(pic_res.content))
|
||||
# 保存图片到本地
|
||||
image.save('tmp_image.jpg')
|
||||
asyncio.run_coroutine_threadsafe(message.reply(file_image='tmp_image.jpg', content=""), self.client.loop)
|
||||
@@ -0,0 +1,18 @@
|
||||
import abc
|
||||
|
||||
class Provider:
|
||||
def __init__(self, cfg):
|
||||
pass
|
||||
|
||||
def text_chat(self, prompt):
|
||||
pass
|
||||
|
||||
def image_chat(self, prompt):
|
||||
pass
|
||||
|
||||
def memory(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def forget(self) -> bool:
|
||||
pass
|
||||
@@ -0,0 +1,398 @@
|
||||
import openai
|
||||
import json
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
from cores.database.conn import dbConn
|
||||
from model.provider.provider import Provider
|
||||
import threading
|
||||
|
||||
abs_path = os.path.dirname(os.path.realpath(sys.argv[0])) + '/'
|
||||
key_record_path = abs_path+'chatgpt_key_record'
|
||||
|
||||
class ProviderOpenAIOfficial(Provider):
|
||||
def __init__(self, cfg):
|
||||
self.key_list = []
|
||||
if 'api_base' in cfg and cfg['api_base'] != 'none' and cfg['api_base'] != '':
|
||||
openai.api_base = cfg['api_base']
|
||||
if cfg['key'] != '' and cfg['key'] != None:
|
||||
print("[System] 读取ChatGPT Key成功")
|
||||
self.key_list = cfg['key']
|
||||
else:
|
||||
input("[System] 请先去完善ChatGPT的Key。详情请前往https://beta.openai.com/account/api-keys")
|
||||
|
||||
# init key record
|
||||
self.init_key_record()
|
||||
|
||||
self.chatGPT_configs = cfg['chatGPTConfigs']
|
||||
print(f'[System] 加载ChatGPTConfigs: {self.chatGPT_configs}')
|
||||
self.openai_configs = cfg
|
||||
# 会话缓存
|
||||
self.session_dict = {}
|
||||
# 最大缓存token
|
||||
self.max_tokens = cfg['total_tokens_limit']
|
||||
# 历史记录持久化间隔时间
|
||||
self.history_dump_interval = 20
|
||||
|
||||
# 读取历史记录
|
||||
try:
|
||||
db1 = dbConn()
|
||||
for session in db1.get_all_session():
|
||||
self.session_dict[session[0]] = json.loads(session[1])['data']
|
||||
print("[System] 历史记录读取成功喵")
|
||||
except BaseException as e:
|
||||
print("[System] 历史记录读取失败: " + str(e))
|
||||
|
||||
# 读取统计信息
|
||||
if not os.path.exists(abs_path+"configs/stat"):
|
||||
with open(abs_path+"configs/stat", 'w', encoding='utf-8') as f:
|
||||
json.dump({}, f)
|
||||
self.stat_file = open(abs_path+"configs/stat", 'r', encoding='utf-8')
|
||||
global count
|
||||
res = self.stat_file.read()
|
||||
if res == '':
|
||||
count = {}
|
||||
else:
|
||||
try:
|
||||
count = json.loads(res)
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
# 创建转储定时器线程
|
||||
threading.Thread(target=self.dump_history, daemon=True).start()
|
||||
|
||||
# 人格
|
||||
self.now_personality = {}
|
||||
|
||||
|
||||
# 转储历史记录的定时器~ Soulter
|
||||
def dump_history(self):
|
||||
time.sleep(10)
|
||||
db = dbConn()
|
||||
while True:
|
||||
try:
|
||||
# print("转储历史记录...")
|
||||
for key in self.session_dict:
|
||||
# print("TEST: "+str(db.get_session(key)))
|
||||
data = self.session_dict[key]
|
||||
data_json = {
|
||||
'data': data
|
||||
}
|
||||
if db.check_session(key):
|
||||
db.update_session(key, json.dumps(data_json))
|
||||
else:
|
||||
db.insert_session(key, json.dumps(data_json))
|
||||
# print("转储历史记录完毕")
|
||||
except BaseException as e:
|
||||
print(e)
|
||||
# 每隔10分钟转储一次
|
||||
time.sleep(10*self.history_dump_interval)
|
||||
|
||||
def text_chat(self, prompt, session_id):
|
||||
# 会话机制
|
||||
if session_id not in self.session_dict:
|
||||
self.session_dict[session_id] = []
|
||||
|
||||
fjson = {}
|
||||
try:
|
||||
f = open(abs_path+"configs/session", "r", encoding="utf-8")
|
||||
fjson = json.loads(f.read())
|
||||
f.close()
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
fjson[session_id] = 'true'
|
||||
f = open(abs_path+"configs/session", "w", encoding="utf-8")
|
||||
f.write(json.dumps(fjson))
|
||||
f.flush()
|
||||
f.close()
|
||||
|
||||
cache_data_list, new_record, req = self.wrap(prompt, session_id)
|
||||
retry = 0
|
||||
response = None
|
||||
while retry < 5:
|
||||
try:
|
||||
response = openai.ChatCompletion.create(
|
||||
messages=req,
|
||||
**self.chatGPT_configs
|
||||
)
|
||||
break
|
||||
except Exception as e:
|
||||
print(e)
|
||||
if 'You exceeded' in str(e) or 'Billing hard limit has been reached' in str(e) or 'No API key provided' in str(e) or 'Incorrect API key provided' in str(e):
|
||||
print("[System] 当前Key已超额或者不正常,正在切换")
|
||||
self.key_stat[openai.api_key]['exceed'] = True
|
||||
self.save_key_record()
|
||||
|
||||
response, is_switched = self.handle_switch_key(req)
|
||||
if not is_switched:
|
||||
# 所有Key都超额或不正常
|
||||
raise e
|
||||
else:
|
||||
break
|
||||
if 'maximum context length' in str(e):
|
||||
print("token超限, 清空对应缓存")
|
||||
self.session_dict[session_id] = []
|
||||
cache_data_list, new_record, req = self.wrap(prompt, session_id)
|
||||
retry+=1
|
||||
if retry >= 5:
|
||||
raise BaseException("连接超时")
|
||||
|
||||
self.key_stat[openai.api_key]['used'] += response['usage']['total_tokens']
|
||||
self.save_key_record()
|
||||
print("[ChatGPT] "+str(response["choices"][0]["message"]["content"]))
|
||||
chatgpt_res = str(response["choices"][0]["message"]["content"]).strip()
|
||||
current_usage_tokens = response['usage']['total_tokens']
|
||||
|
||||
# 超过指定tokens, 尽可能的保留最多的条目,直到小于max_tokens
|
||||
if current_usage_tokens > self.max_tokens:
|
||||
t = current_usage_tokens
|
||||
index = 0
|
||||
while t > self.max_tokens:
|
||||
if index >= len(cache_data_list):
|
||||
break
|
||||
# 保留人格信息
|
||||
if 'user' in cache_data_list[index] and cache_data_list[index]['user']['role'] != 'system':
|
||||
t -= int(cache_data_list[index]['single_tokens'])
|
||||
del cache_data_list[index]
|
||||
else:
|
||||
index += 1
|
||||
# 删除完后更新相关字段
|
||||
self.session_dict[session_id] = cache_data_list
|
||||
# cache_prompt = get_prompts_by_cache_list(cache_data_list)
|
||||
|
||||
# 添加新条目进入缓存的prompt
|
||||
new_record['AI'] = {
|
||||
'role': 'assistant',
|
||||
'content': chatgpt_res,
|
||||
}
|
||||
new_record['usage_tokens'] = current_usage_tokens
|
||||
if len(cache_data_list) > 0:
|
||||
new_record['single_tokens'] = current_usage_tokens - int(cache_data_list[-1]['usage_tokens'])
|
||||
else:
|
||||
new_record['single_tokens'] = current_usage_tokens
|
||||
cache_data_list.append(new_record)
|
||||
|
||||
self.session_dict[session_id] = cache_data_list
|
||||
|
||||
return chatgpt_res
|
||||
|
||||
def image_chat(self, prompt, img_num = 1, img_size = "1024x1024"):
|
||||
retry = 0
|
||||
image_url = ''
|
||||
while retry < 5:
|
||||
try:
|
||||
# print("test1")
|
||||
response = openai.Image.create(
|
||||
prompt=prompt,
|
||||
n=img_num,
|
||||
size=img_size
|
||||
)
|
||||
# print("test2")
|
||||
image_url = []
|
||||
for i in range(img_num):
|
||||
image_url.append(response['data'][i]['url'])
|
||||
print(image_url)
|
||||
break
|
||||
except Exception as e:
|
||||
print(e)
|
||||
if 'You exceeded' in str(e) or 'Billing hard limit has been reached' in str(
|
||||
e) or 'No API key provided' in str(e) or 'Incorrect API key provided' in str(e):
|
||||
print("[System] 当前Key已超额或者不正常,正在切换")
|
||||
self.key_stat[openai.api_key]['exceed'] = True
|
||||
self.save_key_record()
|
||||
|
||||
response, is_switched = self.handle_switch_key(req)
|
||||
if not is_switched:
|
||||
# 所有Key都超额或不正常
|
||||
raise e
|
||||
else:
|
||||
break
|
||||
retry += 1
|
||||
if retry >= 5:
|
||||
raise BaseException("连接超时")
|
||||
|
||||
return image_url
|
||||
|
||||
def forget(self, session_id) -> bool:
|
||||
self.session_dict[session_id] = []
|
||||
return True
|
||||
|
||||
'''
|
||||
获取缓存的会话
|
||||
'''
|
||||
def get_prompts_by_cache_list(self, cache_data_list, divide=False, paging=False, size=5, page=1):
|
||||
prompts = ""
|
||||
if paging:
|
||||
page_begin = (page-1)*size
|
||||
page_end = page*size
|
||||
if page_begin < 0:
|
||||
page_begin = 0
|
||||
if page_end > len(cache_data_list):
|
||||
page_end = len(cache_data_list)
|
||||
cache_data_list = cache_data_list[page_begin:page_end]
|
||||
for item in cache_data_list:
|
||||
prompts += str(item['user']['role']) + ":\n" + str(item['user']['content']) + "\n"
|
||||
prompts += str(item['AI']['role']) + ":\n" + str(item['AI']['content']) + "\n"
|
||||
|
||||
if divide:
|
||||
prompts += "----------\n"
|
||||
return prompts
|
||||
|
||||
|
||||
def get_user_usage_tokens(self,cache_list):
|
||||
usage_tokens = 0
|
||||
for item in cache_list:
|
||||
usage_tokens += int(item['single_tokens'])
|
||||
return usage_tokens
|
||||
|
||||
'''
|
||||
获取统计信息
|
||||
'''
|
||||
def get_stat(self):
|
||||
try:
|
||||
f = open(abs_path+"configs/stat", "r", encoding="utf-8")
|
||||
fjson = json.loads(f.read())
|
||||
f.close()
|
||||
guild_count = 0
|
||||
guild_msg_count = 0
|
||||
guild_direct_msg_count = 0
|
||||
|
||||
for k,v in fjson.items():
|
||||
guild_count += 1
|
||||
guild_msg_count += v['count']
|
||||
guild_direct_msg_count += v['direct_count']
|
||||
|
||||
session_count = 0
|
||||
|
||||
f = open(abs_path+"configs/session", "r", encoding="utf-8")
|
||||
fjson = json.loads(f.read())
|
||||
f.close()
|
||||
for k,v in fjson.items():
|
||||
session_count += 1
|
||||
return guild_count, guild_msg_count, guild_direct_msg_count, session_count
|
||||
except:
|
||||
return -1, -1, -1, -1
|
||||
|
||||
# 包装信息
|
||||
def wrap(self, prompt, session_id):
|
||||
# 获得缓存信息
|
||||
context = self.session_dict[session_id]
|
||||
new_record = {
|
||||
"user": {
|
||||
"role": "user",
|
||||
"content": prompt,
|
||||
},
|
||||
"AI": {},
|
||||
'usage_tokens': 0,
|
||||
}
|
||||
req_list = []
|
||||
for i in context:
|
||||
if 'user' in i:
|
||||
req_list.append(i['user'])
|
||||
if 'AI' in i:
|
||||
req_list.append(i['AI'])
|
||||
req_list.append(new_record['user'])
|
||||
return context, new_record, req_list
|
||||
|
||||
def handle_switch_key(self, req):
|
||||
# messages = [{"role": "user", "content": prompt}]
|
||||
while True:
|
||||
is_all_exceed = True
|
||||
for key in self.key_stat:
|
||||
if key == None:
|
||||
continue
|
||||
if not self.key_stat[key]['exceed']:
|
||||
is_all_exceed = False
|
||||
openai.api_key = key
|
||||
print(f"[System] 切换到Key: {key}, 已使用token: {self.key_stat[key]['used']}")
|
||||
if len(req) > 0:
|
||||
try:
|
||||
response = openai.ChatCompletion.create(
|
||||
messages=req,
|
||||
**self.chatGPT_configs
|
||||
)
|
||||
return response, True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
if 'You exceeded' in str(e):
|
||||
print("[System] 当前Key已超额,正在切换")
|
||||
self.key_stat[openai.api_key]['exceed'] = True
|
||||
self.save_key_record()
|
||||
time.sleep(1)
|
||||
continue
|
||||
else:
|
||||
return True
|
||||
if is_all_exceed:
|
||||
print("[System] 所有Key已超额")
|
||||
return None, False
|
||||
else:
|
||||
print("[System] 在切换key时程序异常。")
|
||||
return None, False
|
||||
|
||||
def getConfigs(self):
|
||||
return self.openai_configs
|
||||
|
||||
def save_key_record(self):
|
||||
with open(key_record_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(self.key_stat, f)
|
||||
|
||||
def get_key_stat(self):
|
||||
return self.key_stat
|
||||
def get_key_list(self):
|
||||
return self.key_list
|
||||
|
||||
# 添加key
|
||||
def append_key(self, key, sponsor):
|
||||
self.key_list.append(key)
|
||||
self.key_stat[key] = {'exceed': False, 'used': 0, 'sponsor': sponsor}
|
||||
self.save_key_record()
|
||||
self.init_key_record()
|
||||
|
||||
# 检查key是否可用
|
||||
def check_key(self, key):
|
||||
pre_key = openai.api_key
|
||||
openai.api_key = key
|
||||
messages = [{"role": "user", "content": "1"}]
|
||||
try:
|
||||
response = openai.ChatCompletion.create(
|
||||
messages=messages,
|
||||
**self.chatGPT_configs
|
||||
)
|
||||
openai.api_key = pre_key
|
||||
return True
|
||||
except Exception as e:
|
||||
pass
|
||||
openai.api_key = pre_key
|
||||
return False
|
||||
|
||||
#将key_list的key转储到key_record中,并记录相关数据
|
||||
def init_key_record(self):
|
||||
if not os.path.exists(key_record_path):
|
||||
with open(key_record_path, 'w', encoding='utf-8') as f:
|
||||
json.dump({}, f)
|
||||
with open(key_record_path, 'r', encoding='utf-8') as keyfile:
|
||||
try:
|
||||
self.key_stat = json.load(keyfile)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.key_stat = {}
|
||||
finally:
|
||||
for key in self.key_list:
|
||||
if key not in self.key_stat:
|
||||
self.key_stat[key] = {'exceed': False, 'used': 0}
|
||||
# if openai.api_key is None:
|
||||
# openai.api_key = key
|
||||
else:
|
||||
# if self.key_stat[key]['exceed']:
|
||||
# print(f"Key: {key} 已超额")
|
||||
# continue
|
||||
# else:
|
||||
# if openai.api_key is None:
|
||||
# openai.api_key = key
|
||||
# print(f"使用Key: {key}, 已使用token: {self.key_stat[key]['used']}")
|
||||
pass
|
||||
if openai.api_key == None:
|
||||
self.handle_switch_key("")
|
||||
self.save_key_record()
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
from revChatGPT.V1 import Chatbot
|
||||
from model.provider.provider import Provider
|
||||
|
||||
class ProviderRevChatGPT(Provider):
|
||||
def __init__(self, config):
|
||||
self.rev_chatgpt = []
|
||||
for i in range(0, len(config['account'])):
|
||||
try:
|
||||
print(f"[System] 创建rev_ChatGPT负载{str(i)}: " + str(config['account'][i]))
|
||||
if 'password' in config['account'][i]:
|
||||
config['account'][i]['password'] = str(config['account'][i]['password'])
|
||||
revstat = {
|
||||
'obj': Chatbot(config=config['account'][i]),
|
||||
'busy': False
|
||||
}
|
||||
self.rev_chatgpt.append(revstat)
|
||||
except BaseException as e:
|
||||
print(f"[System] 创建rev_ChatGPT负载失败: {str(e)}")
|
||||
|
||||
def forget(self) -> bool:
|
||||
return False
|
||||
|
||||
def request_text(self, prompt: str, bot) -> str:
|
||||
resp = ''
|
||||
err_count = 0
|
||||
retry_count = 5
|
||||
|
||||
while err_count < retry_count:
|
||||
try:
|
||||
for data in bot.ask(prompt):
|
||||
resp = data["message"]
|
||||
break
|
||||
except BaseException as e:
|
||||
try:
|
||||
print("[RevChatGPT] 请求出现了一些问题, 正在重试。次数"+str(err_count))
|
||||
err_count += 1
|
||||
if err_count >= retry_count:
|
||||
raise e
|
||||
except BaseException:
|
||||
err_count += 1
|
||||
|
||||
print("[RevChatGPT] "+str(resp))
|
||||
return resp
|
||||
|
||||
def text_chat(self, prompt):
|
||||
res = ''
|
||||
print("[Debug] "+str(self.rev_chatgpt))
|
||||
for revstat in self.rev_chatgpt:
|
||||
if not revstat['busy']:
|
||||
try:
|
||||
revstat['busy'] = True
|
||||
print("[Debug] 使用逆向ChatGPT回复ing", end='', flush=True)
|
||||
res = self.request_text(prompt, revstat['obj'])
|
||||
print("OK")
|
||||
revstat['busy'] = False
|
||||
# 处理结果文本
|
||||
chatgpt_res = res.strip()
|
||||
return res
|
||||
except Exception as e:
|
||||
print("[System-Error] 逆向ChatGPT回复失败" + str(e))
|
||||
try:
|
||||
if e.code == 2:
|
||||
print("[System-Error] 频率限制,正在切换账号。"+ str(e))
|
||||
continue
|
||||
else:
|
||||
res = '所有的非忙碌OpenAI账号经过测试都暂时出现问题,请稍后再试或者联系管理员~'
|
||||
return res
|
||||
except BaseException:
|
||||
continue
|
||||
res = '所有的OpenAI账号都有负载, 请稍后再试~'
|
||||
@@ -0,0 +1,52 @@
|
||||
from model.provider.provider import Provider
|
||||
from EdgeGPT import Chatbot, ConversationStyle
|
||||
import json
|
||||
|
||||
class ProviderRevEdgeGPT(Provider):
|
||||
def __init__(self):
|
||||
self.busy = False
|
||||
self.wait_stack = []
|
||||
with open('./cookies.json', 'r') as f:
|
||||
cookies = json.load(f)
|
||||
self.bot = Chatbot(cookies=cookies)
|
||||
|
||||
def is_busy(self):
|
||||
return self.busy
|
||||
|
||||
async def forget(self):
|
||||
try:
|
||||
await self.bot.reset()
|
||||
return True
|
||||
except BaseException:
|
||||
return False
|
||||
|
||||
async def text_chat(self, prompt):
|
||||
if self.busy:
|
||||
return
|
||||
self.busy = True
|
||||
resp = 'err'
|
||||
err_count = 0
|
||||
retry_count = 5
|
||||
|
||||
while err_count < retry_count:
|
||||
try:
|
||||
resp = await self.bot.ask(prompt=prompt, conversation_style=ConversationStyle.creative)
|
||||
resp = resp['item']['messages'][len(resp['item']['messages'])-1]['text']
|
||||
if 'I\'m sorry but I prefer not to continue this conversation. I\'m still learning so I appreciate your understanding and patience.' in resp:
|
||||
self.busy = False
|
||||
return '', 0
|
||||
if resp == prompt:
|
||||
resp += '\n\n如果你没有让我复述你的话,那代表我可能不想和你继续这个话题了,请输入reset重置会话😶'
|
||||
break
|
||||
except BaseException as e:
|
||||
print(e.with_traceback)
|
||||
err_count += 1
|
||||
if err_count >= retry_count:
|
||||
self.busy = False
|
||||
raise e
|
||||
print("[RevEdgeGPT] 请求出现了一些问题, 正在重试。次数"+str(err_count))
|
||||
self.busy = False
|
||||
|
||||
print("[RevEdgeGPT] "+str(resp))
|
||||
return resp, 1
|
||||
|
||||
+10
-3
@@ -1,3 +1,10 @@
|
||||
requests~=2.28.2
|
||||
openai~=0.26.5
|
||||
qq-botpy~=1.1.2
|
||||
requests
|
||||
openai~=0.27.4
|
||||
qq-botpy
|
||||
revChatGPT~=4.0.8
|
||||
baidu-aip
|
||||
EdgeGPT~=0.1.22.1
|
||||
chardet
|
||||
Pillow
|
||||
GitPython
|
||||
git+https://github.com/Lxns-Network/nakuru-project.git
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import logging
|
||||
from logging.handlers import RotatingFileHandler
|
||||
import colorlog
|
||||
|
||||
logger = logging.getLogger("QQChannelChatGPT")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
handler = colorlog.StreamHandler()
|
||||
fmt = "%(log_color)s[%(name)s] %(message)s"
|
||||
handler.setFormatter(colorlog.ColoredFormatter(
|
||||
fmt))
|
||||
logger.addHandler(handler)
|
||||
Reference in New Issue
Block a user