Compare commits

...

46 Commits

Author SHA1 Message Date
Soulter 743a800b0d perf: 删除一些不必要的log 2023-04-19 17:23:24 +08:00
Soulter a5c43612bf feat: bing模型支持显示信息来源 #70 2023-04-19 17:22:59 +08:00
Soulter e2bd612b8e perf: 优化语言模型载入流程 2023-04-19 17:01:13 +08:00
Soulter 3ddb65e399 fix: 修复bing获取消息数量报错的bug 2023-04-19 16:52:16 +08:00
Soulter 56775580fc feat: bing模型添加单次会话消息条数显示 2023-04-19 16:34:38 +08:00
Soulter 8f7703c158 perf: 强化超出会话限制后自动重置;其他优化 2023-04-19 16:25:07 +08:00
Soulter 7aba9ff3ff fix: 细化依赖库版本 2023-04-18 21:35:09 +08:00
Soulter aea1271a94 perf: 取消程序启动多余的依赖库检查 2023-04-18 21:30:51 +08:00
Soulter b575f195c9 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-04-18 10:54:21 +08:00
Soulter 1eedf7b332 fix: 取消切换模型的权限限制 2023-04-18 10:54:16 +08:00
Soulter d327a1041b Update README.md 2023-04-17 14:40:34 +08:00
Soulter 10a3ba7dd4 Update README.md 2023-04-15 21:44:11 +08:00
Soulter deaa4ea910 Create CODE_OF_CONDUCT.md 2023-04-15 15:33:00 +08:00
Soulter fbfceb3137 fix: 将除去昵称和@后,/开头的消息都视为指令 2023-04-14 22:43:15 +08:00
Soulter e7b9d7cd54 feat: QQ平台支持自定义昵称指令。使用格式: nick 新昵称。默认是ai 2023-04-14 21:54:56 +08:00
Soulter 34aba58351 feat: 更新help说明 2023-04-14 21:10:39 +08:00
Soulter e1639be6c3 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-04-14 21:05:42 +08:00
Soulter 80975c5715 perf: 重做help指令模块 2023-04-14 21:05:39 +08:00
Soulter c12a4f7353 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-04-14 20:49:12 +08:00
Soulter defab688e5 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-04-14 20:32:51 +08:00
Soulter 2244386d33 feat: 针对QQ平台增加私聊模式 #86 2023-04-14 20:31:52 +08:00
Soulter 39244fa27f Update README.md 2023-04-11 19:40:14 +08:00
Soulter 20c19905ac fix: 修复update文本显示的问题 2023-04-11 17:54:24 +08:00
Soulter 8086d645f9 perf: 优化update指令:更新成功后不执行重启命令,需要使用update r重启 2023-04-11 17:50:09 +08:00
Soulter 3a3289bf04 perf: QQ平台@优化 2023-04-11 17:39:29 +08:00
Soulter 1711ff3bb5 fix: bugfixes 2023-04-11 10:53:48 +08:00
Soulter b945913f88 fix: 修复了一些其他问题 2023-04-11 10:50:41 +08:00
Soulter d31533ed82 fix: 修复QQ平台@时使用不了指令的问题 2023-04-11 10:49:10 +08:00
Soulter 0fb2ec2c76 fix: 修复QQ平台@的一些问题 2023-04-11 10:44:01 +08:00
Soulter 89847cbc83 fix: 修复@机器人的已知问题 2023-04-11 10:36:05 +08:00
Soulter 9d12bb23fd fix: 修复@机器人的已知问题 2023-04-11 10:33:46 +08:00
Soulter 79af4ce381 fix: 修复一些已知问题 2023-04-11 10:28:29 +08:00
Soulter 79f293e248 fix: 修复QQ平台@机器人不回复的问题 2023-04-11 10:26:52 +08:00
Soulter e75a0fec01 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-04-11 10:23:29 +08:00
Soulter a935b085d4 perf: QQ平台支持@机器人时回复 2023-04-11 10:23:25 +08:00
Soulter 4ef0a14420 Update README.md 2023-04-11 09:40:38 +08:00
Soulter 8273154904 Update README.md 2023-04-11 09:40:09 +08:00
Soulter 71d6ef3b52 Update README.md 2023-04-11 09:37:14 +08:00
Soulter 119b3a090a Update README.md 2023-04-11 09:34:45 +08:00
Soulter 496df3347b Update README.md 2023-04-11 09:33:58 +08:00
Soulter 2b70eef35b fix: 修复启动时的依赖库更新流程;优化update latest指令 2023-04-10 22:40:26 +08:00
Soulter c4071eedf8 perf: 优化update指令显示 2023-04-10 22:37:08 +08:00
Soulter b6cc866113 Merge branch 'master' of https://github.com/Soulter/QQChannelChatGPT 2023-04-10 22:32:31 +08:00
Soulter 6aabcdeac7 perf: bing模型不再显示正忙,会自动逐个回复。 2023-04-10 22:32:24 +08:00
Soulter 72bccee9e2 Update README.md 2023-04-10 21:54:42 +08:00
Soulter b54f934fcd Update README.md 2023-04-10 01:07:04 +08:00
11 changed files with 586 additions and 118 deletions
+128
View File
@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
SoulterL@outlook.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
+174 -18
View File
@@ -1,14 +1,20 @@
## ⭐体验
<div align="center">
使用手机QQ扫码加入QQ频道(频道名: GPT机器人 | 频道号: x42d56aki2)
# QQChannelChatGPT
在QQ和QQ频道上使用ChatGPT、NewBing等语言模型,稳定,一次部署,同时使用。
<img src="https://user-images.githubusercontent.com/37870767/230417115-9dd3c9d5-6b6b-4928-8fe3-82f559208aab.JPG" width="200"></img>
教程:https://soulter.top/posts/qpdg.html
**Windows用户推荐Windows一键安装,请前往Release下载最新版本(Beta**
有报错请先看issue,解决不了再在频道内反馈。
欢迎体验😊(频道名: GPT机器人 | 频道号: x42d56aki2) | QQ群号:322154837):
<img src="https://user-images.githubusercontent.com/37870767/230417115-9dd3c9d5-6b6b-4928-8fe3-82f559208aab.JPG" width="300"></img>
</div>
## ⭐功能:
通知:部署好后,如果使用的是bing或者逆向ChatGPT库,需要使用切换模型指令`/bing`或者'/revgpt'
近期新功能:
- 支持一键切换语言模型(使用/bing /revgpt /gpt分别可以切换newbing、逆向ChatGPT、官方ChatGPT模型)
- 热更新
@@ -81,7 +87,9 @@
> 关于token:token就相当于是AI中的单词数(但是不等于单词数),`text-davinci-003`模型中最大可以支持`4097`个token。在发送信息时,这个机器人会将用户的历史聊天记录打包发送给ChatGPT,因此,`token`也会相应的累加,为了保证聊天的上下文的逻辑性,就有了缓存token。
### 指令功能
需要先`@`机器人之后再输入指令
#### OpenAI官方API
在频道内需要先`@`机器人之后再输入指令;在QQ中暂时需要在消息前加上`ai `,不需要@
- `/reset`重置prompt
- `/his`查看历史记录(每个用户都有独立的会话)
- `/his [页码数]`查看不同页码的历史记录。例如`/his 2`查看第2页
@@ -91,33 +99,181 @@
- `/help` 查看帮助
- `/key` 动态添加key
- `/set` 人格设置面板
- `/keyword nihao 你好` 设置关键词回复。nihao->你好
- `/bing` 切换为bing
- `/revgpt` 切换为ChatGPT逆向库
- `/画` 画画
#### Bing语言模型
- `/reset`重置prompt
- `/gpt` 切换为OpenAI官方API
- `/revgpt` 切换为ChatGPT逆向库
#### 逆向ChatGPT库语言模型
- `/gpt` 切换为OpenAI官方API
- `/bing` 切换为bing
* 切换模型指令支持临时回复。如`/bing 你好`将会临时使用一次bing模型
## 📰使用方法:
**详细部署教程链接**https://soulter.top/posts/qpdg.html
### 安装第三方库
**Windows用户推荐Windows一键安装,请前往Release下载最新版本(Beta**
有报错请先看issue,解决不了再在频道内反馈。
使用Python的pip工具安装
- `qq-botpy` QQ频道官方Python SDK
- `openai` (OpenAI Python SDK)
### 安装第三方库
```shell
pip install -r requirements.txt
```
> 注意,由于qq-botpy库需要运行在`Python 3.8+`的版本上,因此本项目也需要在此之上运行
> Python版本应>=3.9
### 配置
- 获得 OpenAI的key [OpenAI](https://beta.openai.com/)
- 获得 QQ开放平台下QQ频道机器人的token和appid [QQ开放平台](https://q.qq.com/),一个QQ频道机器人(很容易创建~)
- 在configs/config.yaml下进行配置
**详细部署教程链接**https://soulter.top/posts/qpdg.html
### 启动
- 启动main.py
## DEMO
![1.jpg](screenshots/1.jpg)
![3.jpg](screenshots/3.jpg)
![2.jpg](screenshots/2.jpg)
## ⚙配置文件说明:
```yaml
# 如果你不知道怎么部署,请查看https://soulter.top/posts/qpdg.html
# 不一定需要key了,如果你没有key但有openAI账号或者必应账号,可以考虑使用下面的逆向库
###############平台设置#################
# QQ频道机器人
# QQ开放平台的appid和令牌
# q.qq.com
# enable为true则启用,false则不启用
qqbot:
enable: true
appid:
token:
# QQ机器人
# enable为true则启用,false则不启用
# 需要安装GO-CQHTTP配合使用。
# 文档:https://docs.go-cqhttp.org/
# 请将go-cqhttp的配置文件的sever部分粘贴为以下内容,否则无法使用
# 请先启动go-cqhttp再启动本程序
#
# servers:
# - http:
# host: 127.0.0.1
# version: 0
# port: 5700
# timeout: 5
# - ws:
# address: 127.0.0.1:6700
# middlewares:
# <<: *default
gocqbot:
enable: false
# 设置是否一个人一个会话
uniqueSessionMode: false
# QChannelBot 的版本,请勿修改此字段,否则可能产生一些bug
version: 3.0
# [Beta] 转储历史记录时间间隔(分钟)
dump_history_interval: 10
# 一个用户只能在time秒内发送count条消息
limit:
time: 60
count: 5
# 公告
notice: "此机器人由Github项目QQChannelChatGPT驱动。"
# 是否打开私信功能
# 设置为true则频道成员可以私聊机器人。
# 设置为false则频道成员不能私聊机器人。
direct_message_mode: true
# 系统代理
# http_proxy: http://localhost:7890
# https_proxy: http://localhost:7890
# 自定义回复前缀,如[Rev]或其他,务必加引号以防止不必要的bug。
reply_prefix:
openai_official: "[GPT]"
rev_chatgpt: "[Rev]"
rev_edgegpt: "[RevBing]"
# 百度内容审核服务
# 新用户免费5万次调用。https://cloud.baidu.com/doc/ANTIPORN/index.html
baidu_aip:
enable: false
app_id:
api_key:
secret_key:
###############语言模型设置#################
# OpenAI官方API
# 注意:已支持多key自动切换,方法:
# key:
# - sk-xxxxxx
# - sk-xxxxxx
# 在下方非注释的地方使用以上格式
# 关于api_base:可以使用一些云函数(如腾讯、阿里)来避免国内被墙的问题。
# 详见:
# https://github.com/Ice-Hazymoon/openai-scf-proxy
# https://github.com/Soulter/QQChannelChatGPT/issues/42
# 设置为none则表示使用官方默认api地址
openai:
key:
-
api_base: none
# 这里是GPT配置,语言模型默认使用gpt-3.5-turbo
chatGPTConfigs:
model: gpt-3.5-turbo
max_tokens: 3000
temperature: 0.9
top_p: 1
frequency_penalty: 0
presence_penalty: 0
total_tokens_limit: 5000
# 逆向文心一言【暂时不可用,请勿使用】
rev_ernie:
enable: false
# 逆向New Bing
# 需要在项目根目录下创建cookies.json并粘贴cookies进去。
# 详见:https://soulter.top/posts/qpdg.html
rev_edgegpt:
enable: false
# 逆向ChatGPT库
# https://github.com/acheong08/ChatGPT
# 优点:免费(无免费额度限制);
# 缺点:速度相对慢。OpenAI 速率限制:免费帐户每小时 50 个请求。您可以通过多帐户循环来绕过它
# enable设置为true后,将会停止使用上面正常的官方API调用而使用本逆向项目
#
# 多账户可以保证每个请求都能得到及时的回复。
# 关于account的格式
# account:
# - email: 第1个账户
# password: 第1个账户密码
# - email: 第2个账户
# password: 第2个账户密码
# - ....
# 支持使用access_token登录
# 例:
# - session_token: xxxxx
# - access_token: xxxx
# 请严格按照上面这个格式填写。
# 逆向ChatGPT库的email-password登录方式不工作,建议使用access_token登录
# 获取access_token的方法,详见:https://soulter.top/posts/qpdg.html
rev_ChatGPT:
enable: false
account:
- access_token:
```
+111 -52
View File
@@ -18,8 +18,10 @@ from model.platform.qq import QQ
from nakuru import (
CQHTTP,
GroupMessage,
GroupMemberIncrease,
FriendMessage
)
from nakuru.entities.components import Plain
from nakuru.entities.components import Plain,At
# QQBotClient实例
client = ''
@@ -95,6 +97,7 @@ gocq_app = CQHTTP(
http_port=5700,
)
gocq_loop = None
nick_qq = "ai "
bing_cache_loop = None
@@ -173,27 +176,30 @@ def initBot(cfg, prov):
# 语言模型提供商
if REV_CHATGPT in prov:
if 'account' in cfg['rev_ChatGPT']:
from model.provider.provider_rev_chatgpt import ProviderRevChatGPT
from model.command.command_rev_chatgpt import CommandRevChatGPT
rev_chatgpt = ProviderRevChatGPT(cfg['rev_ChatGPT'])
command_rev_chatgpt = CommandRevChatGPT(cfg['rev_ChatGPT'])
chosen_provider = REV_CHATGPT
else:
input("[System-err] 请退出本程序, 然后在配置文件中填写rev_ChatGPT相关配置")
if cfg['rev_ChatGPT']['enable']:
if 'account' in cfg['rev_ChatGPT']:
from model.provider.provider_rev_chatgpt import ProviderRevChatGPT
from model.command.command_rev_chatgpt import CommandRevChatGPT
rev_chatgpt = ProviderRevChatGPT(cfg['rev_ChatGPT'])
command_rev_chatgpt = CommandRevChatGPT(cfg['rev_ChatGPT'])
chosen_provider = REV_CHATGPT
else:
input("[System-err] 请退出本程序, 然后在配置文件中填写rev_ChatGPT相关配置")
if REV_EDGEGPT in prov:
from model.provider.provider_rev_edgegpt import ProviderRevEdgeGPT
from model.command.command_rev_edgegpt import CommandRevEdgeGPT
rev_edgegpt = ProviderRevEdgeGPT()
command_rev_edgegpt = CommandRevEdgeGPT(rev_edgegpt)
chosen_provider = REV_EDGEGPT
if cfg['rev_edgegpt']['enable']:
from model.provider.provider_rev_edgegpt import ProviderRevEdgeGPT
from model.command.command_rev_edgegpt import CommandRevEdgeGPT
rev_edgegpt = ProviderRevEdgeGPT()
command_rev_edgegpt = CommandRevEdgeGPT(rev_edgegpt)
chosen_provider = REV_EDGEGPT
if OPENAI_OFFICIAL in prov:
from model.provider.provider_openai_official import ProviderOpenAIOfficial
from model.command.command_openai_official import CommandOpenAIOfficial
chatgpt = ProviderOpenAIOfficial(cfg['openai'])
command_openai_official = CommandOpenAIOfficial(chatgpt)
chosen_provider = OPENAI_OFFICIAL
if cfg['openai']['key'] is not None:
from model.provider.provider_openai_official import ProviderOpenAIOfficial
from model.command.command_openai_official import CommandOpenAIOfficial
chatgpt = ProviderOpenAIOfficial(cfg['openai'])
command_openai_official = CommandOpenAIOfficial(chatgpt)
chosen_provider = OPENAI_OFFICIAL
# 得到关键词
if os.path.exists("keyword.json"):
@@ -262,6 +268,19 @@ def initBot(cfg, prov):
print("\n[System] 如果有任何问题, 请在 https://github.com/Soulter/QQChannelChatGPT 上提交issue说明问题!或者添加QQ905617992")
print("[System] 请给 https://github.com/Soulter/QQChannelChatGPT 点个star!")
if chosen_provider is None:
print("[System-Warning] 检测到没有启动任何一个语言模型。请至少在配置文件中启用一个语言模型。")
# 得到指令设置(cmd_config.json)
if os.path.exists("cmd_config.json"):
with open("cmd_config.json", 'r', encoding='utf-8') as f:
cmd_config = json.load(f)
# QQ机器人昵称
if 'nick_qq' in cmd_config:
global nick_qq
nick_qq = cmd_config['nick_qq']
thread_inst = None
# QQ频道
@@ -347,8 +366,9 @@ def send_message(platform, message, res, msg_ref = None, image = None, gocq_loop
'''
处理消息
group: 群聊模式
'''
def oper_msg(message, at=False, msg_ref = None, platform = None):
def oper_msg(message, group=False, msg_ref = None, platform = None):
global session_dict, provider
qq_msg = ''
session_id = ''
@@ -365,18 +385,25 @@ def oper_msg(message, at=False, msg_ref = None, platform = None):
user_name = message.author.username
global qqchan_loop
if platform == PLATFORM_GOCQ:
print("[GOCQ-BOT] 接收到消息:"+ str(message.message[0].text))
user_id = message.group_id
user_name = message.group_id
if isinstance(message.message[0], Plain):
print("[GOCQ-BOT] 接收到消息:"+ str(message.message[0].text))
elif isinstance(message.message[0], At):
print("[GOCQ-BOT] 接收到消息:"+ str(message.message[1].text))
user_id = message.user_id
user_name = message.user_id
global gocq_loop
if chosen_provider is None:
send_message(platform, message, f"没有启动任何一个语言模型。请至少在配置文件中启用一个语言模型。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
# 检查发言频率
if not check_frequency(user_id):
qqchannel_bot.send_qq_msg(message, f'{user_name}的发言超过频率限制(╯▔皿▔)╯。\n{frequency_time}秒内只能提问{frequency_count}次。')
return
if platform == PLATFORM_QQCHAN:
if at:
if group:
# 频道内
# 过滤@
qq_msg = message.content
@@ -400,13 +427,19 @@ def oper_msg(message, at=False, msg_ref = None, platform = None):
session_id = user_id
if platform == PLATFORM_GOCQ:
if isinstance(message.message[0], Plain):
qq_msg = message.message[0].text
if group:
if isinstance(message.message[0], Plain):
qq_msg = str(message.message[0].text)
elif isinstance(message.message[0], At):
qq_msg = str(message.message[1].text).strip()
else:
return
session_id = message.group_id
# todo: 暂时将所有人设为管理员
role = "admin"
else:
return
qq_msg = message.message[0].text
session_id = message.user_id
# todo: 暂时将所有人设为管理员
role = "admin"
logf.write("[QQBOT] "+ qq_msg+'\n')
logf.flush()
@@ -446,9 +479,9 @@ def oper_msg(message, at=False, msg_ref = None, platform = None):
chosen_provider = target
qq_msg = l[1]
else:
if role != "admin":
send_message(platform, message, "你没有权限更换语言模型。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
return
# if role != "admin":
# send_message(platform, message, "你没有权限更换语言模型。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
# return
chosen_provider = target
save_provider_preference(chosen_provider)
send_message(platform, message, f"已切换至【{chosen_provider}", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
@@ -456,9 +489,8 @@ def oper_msg(message, at=False, msg_ref = None, platform = None):
chatgpt_res = ""
if chosen_provider == OPENAI_OFFICIAL:
hit, command_result = command_openai_official.check_command(qq_msg, session_id, user_name, role)
print(f"{hit} {command_result}")
if chosen_provider == OPENAI_OFFICIAL:
hit, command_result = command_openai_official.check_command(qq_msg, session_id, user_name, role, platform=platform)
# hit: 是否触发了指令.
if not hit:
# 请求ChatGPT获得结果
@@ -471,7 +503,7 @@ def oper_msg(message, at=False, msg_ref = None, platform = None):
send_message(platform, message, f"OpenAI API错误。原因如下:\n{str(e)} \n前往官方频道反馈~", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
elif chosen_provider == REV_CHATGPT:
hit, command_result = command_rev_chatgpt.check_command(qq_msg, role)
hit, command_result = command_rev_chatgpt.check_command(qq_msg, role, platform=platform)
if not hit:
try:
chatgpt_res = str(rev_chatgpt.text_chat(qq_msg))
@@ -487,23 +519,24 @@ def oper_msg(message, at=False, msg_ref = None, platform = None):
bing_cache_loop = gocq_loop
elif platform == PLATFORM_QQCHAN:
bing_cache_loop = qqchan_loop
hit, command_result = command_rev_edgegpt.check_command(qq_msg, bing_cache_loop, role)
hit, command_result = command_rev_edgegpt.check_command(qq_msg, bing_cache_loop, role, platform=platform)
if not hit:
try:
if rev_edgegpt.is_busy():
send_message(platform, message, "[RevBing] 正忙,请稍后再试", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
else:
while rev_edgegpt.is_busy():
time.sleep(1)
res, res_code = asyncio.run_coroutine_threadsafe(rev_edgegpt.text_chat(qq_msg), bing_cache_loop).result()
if res_code == 0: # bing不想继续话题,重置会话后重试。
send_message(platform, message, "Bing不想继续话题了, 正在自动重置会话并重试。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
asyncio.run_coroutine_threadsafe(rev_edgegpt.forget(), bing_cache_loop).result()
res, res_code = asyncio.run_coroutine_threadsafe(rev_edgegpt.text_chat(qq_msg), bing_cache_loop).result()
if res_code == 0: # bing不想继续话题,重置会话后重试
send_message(platform, message, "Bing不想继续话题了, 正在自动重置会话并重试。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
if res_code == 0: # bing还是不想继续话题,大概率说明提问有问题
asyncio.run_coroutine_threadsafe(rev_edgegpt.forget(), bing_cache_loop).result()
res, res_code = asyncio.run_coroutine_threadsafe(rev_edgegpt.text_chat(qq_msg), bing_cache_loop).result()
if res_code == 0: # bing还是不想继续话题,大概率说明提问有问题。
send_message(platform, message, "Bing仍然不想继续话题, 请检查您的提问。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
else:
chatgpt_res = str(res)
if REV_EDGEGPT in reply_prefix:
chatgpt_res = reply_prefix[REV_EDGEGPT] + chatgpt_res
send_message(platform, message, "Bing仍然不想继续话题, 会话已重置, 请检查您的提问后重试。", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
res = ""
chatgpt_res = str(res)
if REV_EDGEGPT in reply_prefix:
chatgpt_res = reply_prefix[REV_EDGEGPT] + chatgpt_res
except BaseException as e:
print("[System-Err] Rev NewBing API错误。原因如下:\n"+str(e))
send_message(platform, message, f"Rev NewBing API错误。原因如下:\n{str(e)} \n前往官方频道反馈~", msg_ref=msg_ref, gocq_loop=gocq_loop, qqchannel_bot=qqchannel_bot, gocq_bot=gocq_bot)
@@ -521,6 +554,12 @@ def oper_msg(message, at=False, msg_ref = None, platform = None):
with open("keyword.json", "r", encoding="utf-8") as f:
keywords = json.load(f)
# QQ昵称
if command == "nick":
with open("cmd_config.json", "r", encoding="utf-8") as f:
global nick_qq
nick_qq = json.load(f)["nick_qq"]
if command_result[0]:
# 是否是画图指令
if len(command_result) == 3 and command_result[2] == 'draw':
@@ -611,9 +650,29 @@ class gocqClient():
# 收到群聊消息
@gocq_app.receiver("GroupMessage")
async def _(app: CQHTTP, source: GroupMessage):
global nick_qq
if isinstance(source.message[0], Plain):
if source.message[0].text.startswith('ai '):
source.message[0].text = source.message[0].text[3:]
if source.message[0].text.startswith(nick_qq):
source.message[0].text = source.message[0].text[len(nick_qq):]
new_sub_thread(oper_msg, (source, True, None, PLATFORM_GOCQ))
if isinstance(source.message[0], At):
if source.message[0].qq == source.self_id:
if source.message[1].text.startswith(nick_qq):
source.message[1].text = source.message[0].text[len(nick_qq):]
new_sub_thread(oper_msg, (source, True, None, PLATFORM_GOCQ))
else:
return
return
@gocq_app.receiver("FriendMessage")
async def _(app: CQHTTP, source: FriendMessage):
if isinstance(source.message[0], Plain):
new_sub_thread(oper_msg, (source, False, None, PLATFORM_GOCQ))
else:
return
@gocq_app.receiver("GroupMemberIncrease")
async def _(app: CQHTTP, source: GroupMemberIncrease):
global nick_qq
await app.sendGroupMessage(source.group_id, [
Plain(text=f"欢迎加入本群!\n欢迎给https://github.com/Soulter/QQChannelChatGPT项目一个Star😊~\n@我输入help查看帮助~\n我叫{nick_qq}, 你也可以以【{nick_qq}+问题】的格式来提醒我并问我问题哦~\n")
])
+13 -13
View File
@@ -39,19 +39,19 @@ def check_env():
print("请使用Python3.8运行本项目")
input("按任意键退出...")
exit()
try:
print("检查依赖库中...")
if os.path.exists('requirements.txt'):
os.system("pip3 install -r requirements.txt")
elif os.path.exists('QQChannelChatGPT'+ os.sep +'requirements.txt'):
os.system('QQChannelChatGPT'+ os.sep +'requirements.txt')
os.system("clear")
print("安装依赖库完毕...")
except BaseException as e:
print("安装依赖库失败,请手动安装依赖库。")
print(e)
input("按任意键退出...")
exit()
# try:
# print("检查依赖库中...")
# if os.path.exists('requirements.txt'):
# os.system("pip3 install -r requirements.txt")
# elif os.path.exists('QQChannelChatGPT'+ os.sep +'requirements.txt'):
# os.system('pip3 install -r QQChannelChatGPT'+ os.sep +'requirements.txt')
# os.system("clear")
# print("安装依赖库完毕...")
# except BaseException as e:
# print("安装依赖库失败,请手动安装依赖库。")
# print(e)
# input("按任意键退出...")
# exit()
# 检查key
with open(abs_path+"configs/config.yaml", 'r', encoding='utf-8') as ymlfile:
+75 -14
View File
@@ -4,18 +4,78 @@ import git.exc
from git.repo import Repo
import os
import sys
import requests
from model.provider.provider import Provider
import json
PLATFORM_QQCHAN = 'qqchan'
PLATFORM_GOCQ = 'gocq'
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()
def check_command(self, message, role, platform):
if self.command_start_with(message, "nick"):
return True, self.set_nick(message, platform)
return False, None
'''
存储机器人的昵称
'''
def set_nick(self, message: str, platform: str):
if platform == PLATFORM_GOCQ:
nick = message.split(" ")[1]
self.general_command_storer("nick_qq", nick)
return True, f"设置成功!现在你可以叫我{nick}来提问我啦~", "nick"
elif platform == PLATFORM_QQCHAN:
nick = message.split(" ")[2]
return False, "QQ频道平台不支持为机器人设置昵称。", "nick"
"""
存储指令结果到cmd_config.json
"""
def general_command_storer(self, key, value):
if not os.path.exists("cmd_config.json"):
config = {}
else:
with open("cmd_config.json", "r", encoding="utf-8") as f:
config = json.load(f)
config[key] = value
with open("cmd_config.json", "w", encoding="utf-8") as f:
json.dump(config, f, indent=4, ensure_ascii=False)
f.flush()
def general_commands(self):
return {
"help": "帮助",
"keyword": "设置关键词/关键指令回复",
"update": "更新面板",
"update latest": "更新到最新版本",
"update r": "重启程序",
"reset": "重置会话",
"nick": "设置机器人昵称",
"/bing": "切换到bing模型",
"/gpt": "切换到OpenAI ChatGPT API",
"/revgpt": "切换到网页版ChatGPT",
"/bing 问题": "临时使用一次bing模型进行会话",
"/gpt 问题": "临时使用一次OpenAI ChatGPT API进行会话",
"/revgpt 问题": "临时使用一次网页版ChatGPT进行会话",
}
def help_messager(self, commands: dict):
try:
resp = requests.get("https://soulter.top/channelbot/notice.json").text
notice = json.loads(resp)["notice"]
except BaseException as e:
notice = ""
msg = "Github项目名QQChannelChatGPT, 有问题提交issue, 欢迎Star\n【指令列表】\n"
for key, value in commands.items():
msg += key + ": " + value + "\n"
msg += notice
return msg
# 接受可变参数
def command_start_with(self, message: str, *args):
@@ -40,6 +100,7 @@ class Command:
keyword = {l[1]: l[2]}
with open("keyword.json", "w", encoding="utf-8") as f:
json.dump(keyword, f, ensure_ascii=False, indent=4)
f.flush()
return True, "设置成功: "+l[1]+" -> "+l[2], "keyword"
except BaseException as e:
return False, "设置失败: "+str(e), "keyword"
@@ -63,7 +124,10 @@ class Command:
commits_log = ''
index = 1
for commit in commits:
commits_log += f"[{index}] {commit.message}\n-----------\n"
if commit.message.endswith("\n"):
commits_log += f"[{index}] {commit.message}-----------\n"
else:
commits_log += f"[{index}] {commit.message}\n-----------\n"
index+=1
remote_commit_hash = origin.refs.master.commit.hexsha[:6]
@@ -79,14 +143,6 @@ class Command:
pash_tag = "QQChannelChatGPT"+os.sep
repo.remotes.origin.pull()
try:
os.system("pip3 install -r "+pash_tag+"requirements.txt")
except BaseException as e:
print(str(e))
py = sys.executable
os.execl(py, py, *sys.argv)
# 检查是否是windows环境
# if platform.system().lower() == "windows":
# if os.path.exists("launcher.exe"):
@@ -99,9 +155,14 @@ class Command:
# else:
# py = sys.executable
# os.execl(py, py, *sys.argv)
return True, "更新成功~是否重启?输入update r重启(重启指令不返回任何确认信息)。", "update"
except BaseException as e:
return False, "更新失败: "+str(e), "update"
if l[1] == "r":
py = sys.executable
os.execl(py, py, *sys.argv)
def reset(self):
return False
@@ -116,7 +177,7 @@ class Command:
return False
def help(self):
return True, f"[Github项目名: QQChannelChatGPT,有问题请前往提交issue,欢迎Star此项目~]\n\n指令面板:\nstatus 查看机器人key状态\ncount 查看机器人统计信息\nreset 重置会话\nhis 查看历史记录\ntoken 查看会话token数\nhelp 查看帮助\nset 人格指令菜单\nkey 动态添加key", "help"
return False
def status(self):
return False
+17 -1
View File
@@ -6,7 +6,10 @@ class CommandOpenAIOfficial(Command):
def __init__(self, provider: ProviderOpenAIOfficial):
self.provider = provider
def check_command(self, message: str, session_id: str, user_name: str, role):
def check_command(self, message: str, session_id: str, user_name: str, role, platform: str):
hit, res = super().check_command(message, role, platform)
if hit:
return True, res
if self.command_start_with(message, "reset", "重置"):
return True, self.reset(session_id)
elif self.command_start_with(message, "his", "历史"):
@@ -34,7 +37,20 @@ class CommandOpenAIOfficial(Command):
elif self.command_start_with(message, "key"):
return True, self.key(message, user_name)
if self.command_start_with(message, "/"):
return True, (False, "未知指令", "unknown_command")
return False, None
def help(self):
commands = super().general_commands()
commands[''] = '画画'
commands['key'] = '添加OpenAI key'
commands['set'] = '人格设置面板'
commands['gpt'] = '查看gpt配置信息'
commands['status'] = '查看key使用状态'
commands['token'] = '查看本轮会话token'
return True, super().help_messager(commands), "help"
def reset(self, session_id: str):
+13 -3
View File
@@ -5,15 +5,25 @@ class CommandRevChatGPT(Command):
def __init__(self, provider: ProviderRevChatGPT):
self.provider = provider
def check_command(self, message: str, role):
def check_command(self, message: str, role, platform: str):
hit, res = super().check_command(message, role, platform)
if hit:
return True, res
if self.command_start_with(message, "help", "帮助"):
return True, self.help()
elif self.command_start_with(message, "reset"):
return True, self.reset()
elif self.command_start_with(message, "update"):
return True, self.update(message, role)
elif self.command_start_with(message, "keyword"):
return True, self.keyword(message, role)
if self.command_start_with(message, "/"):
return True, (False, "未知指令", "unknown_command")
return False, None
def reset(self):
return False, "此功能暂未开放", "reset"
def help(self):
return True, "[Github项目名: QQChannelChatGPT,有问题请前往提交issue,欢迎Star此项目~]\n\nRevChatGPT指令面板:\n当前语言模型RevChatGPT未实现任何指令\n", "help"
return True, super().help_messager(super().general_commands()), "help"
+8 -2
View File
@@ -5,7 +5,10 @@ class CommandRevEdgeGPT(Command):
def __init__(self, provider: ProviderRevEdgeGPT):
self.provider = provider
def check_command(self, message: str, loop, role):
def check_command(self, message: str, loop, role, platform: str):
hit, res = super().check_command(message, role, platform)
if hit:
return True, res
if self.command_start_with(message, "reset"):
return True, self.reset(loop)
elif self.command_start_with(message, "help"):
@@ -14,6 +17,9 @@ class CommandRevEdgeGPT(Command):
return True, self.update(message, role)
elif self.command_start_with(message, "keyword"):
return True, self.keyword(message, role)
if self.command_start_with(message, "/"):
return True, (False, "未知指令", "unknown_command")
return False, None
def reset(self, loop):
@@ -25,5 +31,5 @@ class CommandRevEdgeGPT(Command):
return res, "重置失败", "reset"
def help(self):
return True, "[Github项目名: QQChannelChatGPT,有问题请前往提交issue,欢迎Star此项目~]\n\nRevBing指令面板:\nreset: 重置\nhelp: 帮助", "help"
return True, super().help_messager(super().general_commands()), "help"
+8 -3
View File
@@ -8,6 +8,11 @@ class QQ:
async def send_qq_msg(self, source, res):
print("[System-Info] 回复QQ消息中..."+res)
# 通过消息链处理
await self.client.sendGroupMessage(source.group_id, [
Plain(text=res)
])
if source.type == "GroupMessage":
await self.client.sendGroupMessage(source.group_id, [
Plain(text=res)
])
elif source.type == "FriendMessage":
await self.client.sendFriendMessage(source.user_id, [
Plain(text=res)
])
+33 -6
View File
@@ -31,15 +31,42 @@ class ProviderRevEdgeGPT(Provider):
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']
# print("[RevEdgeGPT] "+str(resp))
msj_obj = resp['item']['messages'][len(resp['item']['messages'])-1]
reply_msg = msj_obj['text']
if 'sourceAttributions' in msj_obj:
reply_source = msj_obj['sourceAttributions']
else:
reply_source = []
if 'throttling' in resp['item']:
throttling = resp['item']['throttling']
# print(throttling)
else:
throttling = None
if 'I\'m sorry but I prefer not to continue this conversation. I\'m still learning so I appreciate your understanding and patience.' in resp:
self.busy = False
return '', 0
if resp == prompt:
resp += '\n\n如果你没有让我复述你的话,那代表我可能不想和你继续这个话题了,请输入reset重置会话😶'
if reply_msg == prompt:
# resp += '\n\n如果你没有让我复述你的话,那代表我可能不想和你继续这个话题了,请输入reset重置会话😶'
await self.forget()
err_count += 1
continue
if reply_msg is None:
# 不想答复
return '', 0
else:
index = 1
if len(reply_source) > 0:
reply_msg += "\n\n信息来源:\n"
for i in reply_source:
reply_msg += f"[{str(index)}]: {i['seeMoreUrl']} | {i['providerDisplayName']}\n"
index += 1
if throttling is not None:
reply_msg += f"\n{throttling['numUserMessagesInConversation']}/{throttling['maxNumUserMessagesInConversation']}"
break
except BaseException as e:
print(e.with_traceback)
# raise e
print(e)
err_count += 1
if err_count >= retry_count:
self.busy = False
@@ -47,6 +74,6 @@ class ProviderRevEdgeGPT(Provider):
print("[RevEdgeGPT] 请求出现了一些问题, 正在重试。次数"+str(err_count))
self.busy = False
print("[RevEdgeGPT] "+str(resp))
return resp, 1
print("[RevEdgeGPT] "+str(reply_msg))
return reply_msg, 1
+6 -6
View File
@@ -1,10 +1,10 @@
requests
requests~=2.28.1
openai~=0.27.4
qq-botpy
qq-botpy~=1.1.2
revChatGPT~=4.0.8
baidu-aip
baidu-aip~=4.16.9
EdgeGPT~=0.1.22.1
chardet
Pillow
GitPython
chardet~=5.1.0
Pillow~=9.4.0
GitPython~=3.1.31
git+https://github.com/Lxns-Network/nakuru-project.git