mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-04 12:56:02 +00:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8dbd426ae | ||
|
|
40d6e809a0 | ||
|
|
236c540d18 | ||
|
|
d6ca059f6c | ||
|
|
52c06a60ca | ||
|
|
6353644ec3 | ||
|
|
20df9ded3d | ||
|
|
7569b18a4c | ||
|
|
b9da4f4951 | ||
|
|
89b9e29257 | ||
|
|
d605de9de4 | ||
|
|
d46c94d7c3 | ||
|
|
2db9c00530 | ||
|
|
66d8d159f9 | ||
|
|
9fa1446284 | ||
|
|
b3e4cb48c7 | ||
|
|
0bca7b2247 | ||
|
|
7812e03c9d | ||
|
|
7a852ae5af | ||
|
|
706d9e61c1 | ||
|
|
8f0ed4ff4b | ||
|
|
3415b6f121 | ||
|
|
256ba6fb86 | ||
|
|
d30b2b9afe | ||
|
|
be943ca1fc | ||
|
|
1ddab2a97a | ||
|
|
e15fd4695c | ||
|
|
ffa4b1b4a1 | ||
|
|
f8eee3a2a6 | ||
|
|
eeee7a8343 | ||
|
|
8447b73fcb | ||
|
|
2863945d5f | ||
|
|
cb1f8ca6f7 |
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
### 事务
|
### 事务
|
||||||
|
|
||||||
- [ ] 已阅读仓库[贡献指引](../CONTRIBUTING.md)
|
- [ ] 已阅读仓库[贡献指引](https://github.com/RockChinQ/QChatGPT/blob/master/CONTRIBUTING.md)
|
||||||
- [ ] 已与维护者在issues或其他平台沟通此PR大致内容
|
- [ ] 已与维护者在issues或其他平台沟通此PR大致内容
|
||||||
|
|
||||||
## 以下内容可在起草PR后、合并PR前逐步完成
|
## 以下内容可在起草PR后、合并PR前逐步完成
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,5 +17,6 @@ scenario/
|
|||||||
override.json
|
override.json
|
||||||
cookies.json
|
cookies.json
|
||||||
res/announcement_saved
|
res/announcement_saved
|
||||||
|
res/announcement_saved.json
|
||||||
cmdpriv.json
|
cmdpriv.json
|
||||||
tips.py
|
tips.py
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
# QChatGPT🤖
|
# QChatGPT🤖
|
||||||
|
|
||||||
|
[English](README_en.md) | 简体中文
|
||||||
|
|
||||||
|
[](https://github.com/RockChinQ/QChatGPT/releases/latest)
|
||||||
|
|
||||||
> 2023/3/18 现已支持GPT-4 API(内测),请查看`config-template.py`中的`completion_api_params`
|
> 2023/3/18 现已支持GPT-4 API(内测),请查看`config-template.py`中的`completion_api_params`
|
||||||
> 2023/3/15 逆向库已支持New Bing,使用方法查看[插件文档](https://github.com/RockChinQ/revLibs)
|
> 2023/3/15 逆向库已支持New Bing,使用方法查看[插件文档](https://github.com/RockChinQ/revLibs)
|
||||||
|
|
||||||
@@ -257,6 +261,7 @@ python3 main.py
|
|||||||
- [RockChinQ/WaitYiYan](https://github.com/RockChinQ/WaitYiYan) - 实时获取百度`文心一言`等待列表人数
|
- [RockChinQ/WaitYiYan](https://github.com/RockChinQ/WaitYiYan) - 实时获取百度`文心一言`等待列表人数
|
||||||
- [chordfish-k/QChartGPT_Emoticon_Plugin](https://github.com/chordfish-k/QChartGPT_Emoticon_Plugin) - 使机器人根据回复内容发送表情包
|
- [chordfish-k/QChartGPT_Emoticon_Plugin](https://github.com/chordfish-k/QChartGPT_Emoticon_Plugin) - 使机器人根据回复内容发送表情包
|
||||||
- [oliverkirk-sudo/ChatPoeBot](https://github.com/oliverkirk-sudo/ChatPoeBot) - 接入[Poe](https://poe.com/)上的机器人
|
- [oliverkirk-sudo/ChatPoeBot](https://github.com/oliverkirk-sudo/ChatPoeBot) - 接入[Poe](https://poe.com/)上的机器人
|
||||||
|
- [lieyanqzu/WeatherPlugin](https://github.com/lieyanqzu/WeatherPlugin) - 天气查询插件
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## 😘致谢
|
## 😘致谢
|
||||||
|
|||||||
194
README_en.md
Normal file
194
README_en.md
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
# QChatGPT🤖
|
||||||
|
|
||||||
|
English | [简体中文](README.md)
|
||||||
|
|
||||||
|
[](https://github.com/RockChinQ/QChatGPT/releases/latest)
|
||||||
|
|
||||||
|
- Refer to [Wiki](https://github.com/RockChinQ/QChatGPT/wiki) to get further information.
|
||||||
|
- Official QQ group: 656285629
|
||||||
|
- Community QQ group: 362515018
|
||||||
|
- QQ channel robot: [QQChannelChatGPT](https://github.com/Soulter/QQChannelChatGPT)
|
||||||
|
- Any contribution is welcome, please refer to [CONTRIBUTING.md](CONTRIBUTING.md)
|
||||||
|
|
||||||
|
## 🍺List of supported models
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Details</summary>
|
||||||
|
|
||||||
|
### Chat
|
||||||
|
|
||||||
|
- OpenAI GPT-3.5 (ChatGPT API), default model
|
||||||
|
- OpenAI GPT-3, supported natively, switch to it in `config.py`
|
||||||
|
- OpenAI GPT-4, supported natively, qualification for internal testing required, switch to it in `config.py`
|
||||||
|
- ChatGPT website edition (GPT-3.5), see [revLibs plugin](https://github.com/RockChinQ/revLibs)
|
||||||
|
- ChatGPT website edition (GPT-4), ChatGPT plus subscription required, see [revLibs plugin](https://github.com/RockChinQ/revLibs)
|
||||||
|
- New Bing, see [revLibs plugin](https://github.com/RockChinQ/revLibs)
|
||||||
|
|
||||||
|
### Story
|
||||||
|
|
||||||
|
- NovelAI API, see [QCPNovelAi plugin](https://github.com/dominoar/QCPNovelAi)
|
||||||
|
|
||||||
|
### Image
|
||||||
|
|
||||||
|
- OpenAI DALL·E, supported natively, see [Wiki(cn)](https://github.com/RockChinQ/QChatGPT/wiki/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8#%E5%8A%9F%E8%83%BD%E7%82%B9%E5%88%97%E4%B8%BE)
|
||||||
|
- NovelAI API, see [QCPNovelAi plugin](https://github.com/dominoar/QCPNovelAi)
|
||||||
|
|
||||||
|
### Voice
|
||||||
|
|
||||||
|
- TTS+VITS, see [QChatPlugins](https://github.com/dominoar/QChatPlugins)
|
||||||
|
- Plachta/VITS-Umamusume-voice-synthesizer, see [chat_voice plugin](https://github.com/oliverkirk-sudo/chat_voice)
|
||||||
|
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
Install this [plugin](https://github.com/RockChinQ/Switcher) to switch between different models.
|
||||||
|
|
||||||
|
## ✅Function Points
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Details</summary>
|
||||||
|
|
||||||
|
- ✅Sensitive word filtering, avoid being banned
|
||||||
|
- ✅Multiple responding rules, including regular expression matching
|
||||||
|
- ✅Multiple api-key management, automatic switching when exceeding
|
||||||
|
- ✅Support for customizing the preset prompt text
|
||||||
|
- ✅Chat, story, image, voice, etc. models are supported
|
||||||
|
- ✅Support for hot reloading and hot updating
|
||||||
|
- ✅Support for plugin loading
|
||||||
|
- ✅Blacklist mechanism for private chat and group chat
|
||||||
|
- ✅Excellent long message processing strategy
|
||||||
|
- ✅Reply rate limitation
|
||||||
|
- ✅Support for network proxy
|
||||||
|
- ✅Support for customizing the output format
|
||||||
|
</details>
|
||||||
|
|
||||||
|
More details, see [Wiki(cn)](https://github.com/RockChinQ/QChatGPT/wiki/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8#%E5%8A%9F%E8%83%BD%E7%82%B9%E5%88%97%E4%B8%BE)
|
||||||
|
|
||||||
|
## 🔩Deployment
|
||||||
|
|
||||||
|
**If you encounter any problems during deployment, please search in the issue of [QChatGPT](https://github.com/RockChinQ/QChatGPT/issues) or [qcg-installer](https://github.com/RockChinQ/qcg-installer/issues) first.**
|
||||||
|
|
||||||
|
### - Register OpenAI account
|
||||||
|
|
||||||
|
> If you want to use a model other than OpenAI (such as New Bing), you can skip this step and directly refer to following steps, and then configure it according to the relevant plugin documentation.
|
||||||
|
|
||||||
|
To register OpenAI account, please refer to the following articles(in Chinese):
|
||||||
|
|
||||||
|
> [国内注册ChatGPT的方法(100%可用)](https://www.pythonthree.com/register-openai-chatgpt/)
|
||||||
|
> [手把手教你如何注册ChatGPT,超级详细](https://guxiaobei.com/51461)
|
||||||
|
|
||||||
|
Check your api-key in [personal center](https://beta.openai.com/account/api-keys) after registration, and then follow the following steps to deploy.
|
||||||
|
|
||||||
|
### - Deploy Automatically
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Details</summary>
|
||||||
|
|
||||||
|
#### Docker
|
||||||
|
|
||||||
|
See [this document(cn)](res/docs/docker_deploy.md)
|
||||||
|
Contributed by [@mikumifa](https://github.com/mikumifa)
|
||||||
|
|
||||||
|
#### Installer
|
||||||
|
|
||||||
|
Use [this installer](https://github.com/RockChinQ/qcg-installer) to deploy.
|
||||||
|
|
||||||
|
- The installer currently only supports some platforms, please refer to the repository document for details, and manually deploy for other platforms
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### - Deploy Manually
|
||||||
|
<details>
|
||||||
|
<summary>Manually deployment supports any platforms</summary>
|
||||||
|
|
||||||
|
- Python 3.9.x or higher
|
||||||
|
|
||||||
|
#### Configure Mirai
|
||||||
|
|
||||||
|
Follow [this tutorial(cn)](https://yiri-mirai.wybxc.cc/tutorials/01/configuration) to configure Mirai and YiriMirai.
|
||||||
|
After starting mirai-console, use the `login` command to log in to the QQ account, and keep the mirai-console running.
|
||||||
|
|
||||||
|
#### Configure QChatGPT
|
||||||
|
|
||||||
|
1. Clone the repository
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/RockChinQ/QChatGPT
|
||||||
|
cd QChatGPT
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Install dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip3 install requests yiri-mirai openai colorlog func_timeout dulwich Pillow
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Generate `config.py`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Edit `config.py`
|
||||||
|
|
||||||
|
5. Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Any problems, please refer to the issues page.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## 🚀Usage
|
||||||
|
|
||||||
|
**After deployment, please read: [Commands(cn)](https://github.com/RockChinQ/QChatGPT/wiki/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8#%E6%9C%BA%E5%99%A8%E4%BA%BA%E6%8C%87%E4%BB%A4)**
|
||||||
|
|
||||||
|
**For more details, please refer to the [Wiki(cn)](https://github.com/RockChinQ/QChatGPT/wiki/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8#%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F)**
|
||||||
|
|
||||||
|
|
||||||
|
## 🧩Plugin Ecosystem
|
||||||
|
|
||||||
|
Plugin [usage](https://github.com/RockChinQ/QChatGPT/wiki/%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8) and [development](https://github.com/RockChinQ/QChatGPT/wiki/%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91) are supported.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>List of plugins (cn)</summary>
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
在`tests/plugin_examples`目录下,将其整个目录复制到`plugins`目录下即可使用
|
||||||
|
|
||||||
|
- `cmdcn` - 主程序指令中文形式
|
||||||
|
- `hello_plugin` - 在收到消息`hello`时回复相应消息
|
||||||
|
- `urlikethisijustsix` - 收到冒犯性消息时回复相应消息
|
||||||
|
|
||||||
|
### More Plugins
|
||||||
|
|
||||||
|
欢迎提交新的插件
|
||||||
|
|
||||||
|
- [revLibs](https://github.com/RockChinQ/revLibs) - 将ChatGPT网页版接入此项目,关于[官方接口和网页版有什么区别](https://github.com/RockChinQ/QChatGPT/wiki/%E5%AE%98%E6%96%B9%E6%8E%A5%E5%8F%A3%E4%B8%8EChatGPT%E7%BD%91%E9%A1%B5%E7%89%88)
|
||||||
|
- [Switcher](https://github.com/RockChinQ/Switcher) - 支持通过指令切换使用的模型
|
||||||
|
- [hello_plugin](https://github.com/RockChinQ/hello_plugin) - `hello_plugin` 的储存库形式,插件开发模板
|
||||||
|
- [dominoar/QChatPlugins](https://github.com/dominoar/QchatPlugins) - dominoar编写的诸多新功能插件(语音输出、Ranimg、屏蔽词规则等)
|
||||||
|
- [dominoar/QCP-NovelAi](https://github.com/dominoar/QCP-NovelAi) - NovelAI 故事叙述与绘画
|
||||||
|
- [oliverkirk-sudo/chat_voice](https://github.com/oliverkirk-sudo/chat_voice) - 文字转语音输出,使用HuggingFace上的[VITS-Umamusume-voice-synthesizer模型](https://huggingface.co/spaces/Plachta/VITS-Umamusume-voice-synthesizer)
|
||||||
|
- [RockChinQ/WaitYiYan](https://github.com/RockChinQ/WaitYiYan) - 实时获取百度`文心一言`等待列表人数
|
||||||
|
- [chordfish-k/QChartGPT_Emoticon_Plugin](https://github.com/chordfish-k/QChartGPT_Emoticon_Plugin) - 使机器人根据回复内容发送表情包
|
||||||
|
- [oliverkirk-sudo/ChatPoeBot](https://github.com/oliverkirk-sudo/ChatPoeBot) - 接入[Poe](https://poe.com/)上的机器人
|
||||||
|
- [lieyanqzu/WeatherPlugin](https://github.com/lieyanqzu/WeatherPlugin) - 天气查询插件
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## 😘Thanks
|
||||||
|
|
||||||
|
- [@the-lazy-me](https://github.com/the-lazy-me) video tutorial creator
|
||||||
|
- [@mikumifa](https://github.com/mikumifa) Docker deployment
|
||||||
|
- [@dominoar](https://github.com/dominoar) Plugin development
|
||||||
|
- [@万神的星空](https://github.com/qq255204159) Packages publisher
|
||||||
|
- [@ljcduo](https://github.com/ljcduo) GPT-4 API internal test account
|
||||||
|
|
||||||
|
And all [contributors](https://github.com/RockChinQ/QChatGPT/graphs/contributors) and other friends who support this project.
|
||||||
|
|
||||||
|
<!-- ## 👍赞赏
|
||||||
|
|
||||||
|
<img alt="赞赏码" src="res/mm_reward_qrcode_1672840549070.png" width="400" height="400"/> -->
|
||||||
@@ -212,6 +212,12 @@ blob_message_threshold = 256
|
|||||||
# - "forward": 将长消息转换为转发消息组件发送
|
# - "forward": 将长消息转换为转发消息组件发送
|
||||||
blob_message_strategy = "forward"
|
blob_message_strategy = "forward"
|
||||||
|
|
||||||
|
# 允许等待
|
||||||
|
# 同一会话内,是否等待上一条消息处理完成后再处理下一条消息
|
||||||
|
# 若设置为False,若上一条未处理完时收到了新消息,将会丢弃新消息
|
||||||
|
# 丢弃消息时的提示信息可以在tips.py中修改
|
||||||
|
wait_last_done = True
|
||||||
|
|
||||||
# 文字转图片时使用的字体文件路径
|
# 文字转图片时使用的字体文件路径
|
||||||
# 当策略为"image"时生效
|
# 当策略为"image"时生效
|
||||||
# 若在Windows系统下,程序会自动使用Windows自带的微软雅黑字体
|
# 若在Windows系统下,程序会自动使用Windows自带的微软雅黑字体
|
||||||
@@ -233,26 +239,49 @@ hide_exce_info_to_user = False
|
|||||||
sys_pool_num = 8
|
sys_pool_num = 8
|
||||||
|
|
||||||
# 执行管理员请求和指令的线程池并行线程数量,一般和管理员数量相等
|
# 执行管理员请求和指令的线程池并行线程数量,一般和管理员数量相等
|
||||||
admin_pool_num = 2
|
admin_pool_num = 4
|
||||||
|
|
||||||
# 执行用户请求和指令的线程池并行线程数量
|
# 执行用户请求和指令的线程池并行线程数量
|
||||||
# 如需要更高的并发,可以增大该值
|
# 如需要更高的并发,可以增大该值
|
||||||
user_pool_num = 6
|
user_pool_num = 8
|
||||||
|
|
||||||
# 每个会话的过期时间,单位为秒
|
# 每个会话的过期时间,单位为秒
|
||||||
# 默认值20分钟
|
# 默认值20分钟
|
||||||
session_expire_time = 60 * 20
|
session_expire_time = 1200
|
||||||
|
|
||||||
# 会话限速
|
# 会话限速
|
||||||
# 单会话内每分钟可进行的对话次数
|
# 单会话内每分钟可进行的对话次数
|
||||||
# 若不需要限速,可以设置为一个很大的值
|
# 若不需要限速,可以设置为一个很大的值
|
||||||
# 默认值60次,基本上不会触发限速
|
# 默认值60次,基本上不会触发限速
|
||||||
rate_limitation = 60
|
#
|
||||||
|
# 若要设置针对某特定群的限速,请使用如下格式:
|
||||||
|
# {
|
||||||
|
# "group_<群号>": 60,
|
||||||
|
# "default": 60,
|
||||||
|
# }
|
||||||
|
# 若要设置针对某特定用户私聊的限速,请使用如下格式:
|
||||||
|
# {
|
||||||
|
# "person_<用户QQ>": 60,
|
||||||
|
# "default": 60,
|
||||||
|
# }
|
||||||
|
# 同时设置多个群和私聊的限速,示例:
|
||||||
|
# {
|
||||||
|
# "group_12345678": 60,
|
||||||
|
# "group_87654321": 60,
|
||||||
|
# "person_234567890": 60,
|
||||||
|
# "person_345678901": 60,
|
||||||
|
# "default": 60,
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# 注意: 未指定的都使用default的限速值,default不可删除
|
||||||
|
rate_limitation = {
|
||||||
|
"default": 60,
|
||||||
|
}
|
||||||
|
|
||||||
# 会话限速策略
|
# 会话限速策略
|
||||||
# - "wait": 每次对话获取到回复时,等待一定时间再发送回复,保证其不会超过限速均值
|
# - "wait": 每次对话获取到回复时,等待一定时间再发送回复,保证其不会超过限速均值
|
||||||
# - "drop": 此分钟内,若对话次数超过限速次数,则丢弃之后的对话,每自然分钟重置
|
# - "drop": 此分钟内,若对话次数超过限速次数,则丢弃之后的对话,每自然分钟重置
|
||||||
rate_limit_strategy = "wait"
|
rate_limit_strategy = "drop"
|
||||||
|
|
||||||
# 是否在启动时进行依赖库更新
|
# 是否在启动时进行依赖库更新
|
||||||
upgrade_dependencies = True
|
upgrade_dependencies = True
|
||||||
|
|||||||
91
main.py
91
main.py
@@ -11,6 +11,8 @@ import traceback
|
|||||||
|
|
||||||
sys.path.append(".")
|
sys.path.append(".")
|
||||||
|
|
||||||
|
from pkg.utils.log import init_runtime_log_file, reset_logging
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import colorlog
|
import colorlog
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -18,6 +20,7 @@ except ImportError:
|
|||||||
import pkg.utils.pkgmgr as pkgmgr
|
import pkg.utils.pkgmgr as pkgmgr
|
||||||
try:
|
try:
|
||||||
pkgmgr.install_requirements("requirements.txt")
|
pkgmgr.install_requirements("requirements.txt")
|
||||||
|
pkgmgr.install_upgrade("websockets")
|
||||||
import colorlog
|
import colorlog
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print("依赖不满足,请查看 https://github.com/RockChinQ/qcg-installer/issues/15")
|
print("依赖不满足,请查看 https://github.com/RockChinQ/qcg-installer/issues/15")
|
||||||
@@ -30,13 +33,9 @@ from urllib3.exceptions import InsecureRequestWarning
|
|||||||
import pkg.utils.context
|
import pkg.utils.context
|
||||||
|
|
||||||
|
|
||||||
log_colors_config = {
|
# 是否使用override.json覆盖配置
|
||||||
'DEBUG': 'green', # cyan white
|
# 仅在启动时提供 --override 或 -r 参数时生效
|
||||||
'INFO': 'white',
|
use_override = False
|
||||||
'WARNING': 'yellow',
|
|
||||||
'ERROR': 'red',
|
|
||||||
'CRITICAL': 'cyan',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def init_db():
|
def init_db():
|
||||||
@@ -55,55 +54,18 @@ def ensure_dependencies():
|
|||||||
|
|
||||||
known_exception_caught = False
|
known_exception_caught = False
|
||||||
|
|
||||||
log_file_name = "qchatgpt.log"
|
|
||||||
|
|
||||||
|
|
||||||
def init_runtime_log_file():
|
|
||||||
"""为此次运行生成日志文件
|
|
||||||
格式: qchatgpt-yyyy-MM-dd-HH-mm-ss.log
|
|
||||||
"""
|
|
||||||
global log_file_name
|
|
||||||
|
|
||||||
# 检查logs目录是否存在
|
|
||||||
if not os.path.exists("logs"):
|
|
||||||
os.mkdir("logs")
|
|
||||||
|
|
||||||
# 检查本目录是否有qchatgpt.log,若有,移动到logs目录
|
|
||||||
if os.path.exists("qchatgpt.log"):
|
|
||||||
shutil.move("qchatgpt.log", "logs/qchatgpt.legacy.log")
|
|
||||||
|
|
||||||
log_file_name = "logs/qchatgpt-%s.log" % time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
|
|
||||||
|
|
||||||
|
|
||||||
def reset_logging():
|
|
||||||
global log_file_name
|
|
||||||
|
|
||||||
|
def override_config():
|
||||||
import config
|
import config
|
||||||
|
# 检查override.json覆盖
|
||||||
if pkg.utils.context.context['logger_handler'] is not None:
|
if os.path.exists("override.json") and use_override:
|
||||||
logging.getLogger().removeHandler(pkg.utils.context.context['logger_handler'])
|
override_json = json.load(open("override.json", "r", encoding="utf-8"))
|
||||||
|
for key in override_json:
|
||||||
for handler in logging.getLogger().handlers:
|
if hasattr(config, key):
|
||||||
logging.getLogger().removeHandler(handler)
|
setattr(config, key, override_json[key])
|
||||||
|
logging.info("覆写配置[{}]为[{}]".format(key, override_json[key]))
|
||||||
logging.basicConfig(level=config.logging_level, # 设置日志输出格式
|
else:
|
||||||
filename=log_file_name, # log日志输出的文件位置和文件名
|
logging.error("无法覆写配置[{}]为[{}],该配置不存在,请检查override.json是否正确".format(key, override_json[key]))
|
||||||
format="[%(asctime)s.%(msecs)03d] %(filename)s (%(lineno)d) - [%(levelname)s] : %(message)s",
|
|
||||||
# 日志输出的格式
|
|
||||||
# -8表示占位符,让输出左对齐,输出长度都为8位
|
|
||||||
datefmt="%Y-%m-%d %H:%M:%S" # 时间输出的格式
|
|
||||||
)
|
|
||||||
sh = logging.StreamHandler()
|
|
||||||
sh.setLevel(config.logging_level)
|
|
||||||
sh.setFormatter(colorlog.ColoredFormatter(
|
|
||||||
fmt="%(log_color)s[%(asctime)s.%(msecs)03d] %(filename)s (%(lineno)d) - [%(levelname)s] : "
|
|
||||||
"%(message)s",
|
|
||||||
datefmt="%Y-%m-%d %H:%M:%S",
|
|
||||||
log_colors=log_colors_config
|
|
||||||
))
|
|
||||||
logging.getLogger().addHandler(sh)
|
|
||||||
pkg.utils.context.context['logger_handler'] = sh
|
|
||||||
return sh
|
|
||||||
|
|
||||||
|
|
||||||
# 临时函数,用于加载config和上下文,未来统一放在config类
|
# 临时函数,用于加载config和上下文,未来统一放在config类
|
||||||
@@ -123,17 +85,10 @@ def load_config():
|
|||||||
logging.warning("配置文件不完整,您可以依据config-template.py检查config.py")
|
logging.warning("配置文件不完整,您可以依据config-template.py检查config.py")
|
||||||
|
|
||||||
# 检查override.json覆盖
|
# 检查override.json覆盖
|
||||||
if os.path.exists("override.json"):
|
override_config()
|
||||||
override_json = json.load(open("override.json", "r", encoding="utf-8"))
|
|
||||||
for key in override_json:
|
|
||||||
if hasattr(config, key):
|
|
||||||
setattr(config, key, override_json[key])
|
|
||||||
logging.info("覆写配置[{}]为[{}]".format(key, override_json[key]))
|
|
||||||
else:
|
|
||||||
logging.error("无法覆写配置[{}]为[{}],该配置不存在,请检查override.json是否正确".format(key, override_json[key]))
|
|
||||||
|
|
||||||
if not is_integrity:
|
if not is_integrity:
|
||||||
logging.warning("以上配置已被设为默认值,将在3秒后继续启动... ")
|
logging.warning("以上不存在的配置已被设为默认值,将在3秒后继续启动... ")
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
|
|
||||||
# 存进上下文
|
# 存进上下文
|
||||||
@@ -348,8 +303,9 @@ def start(first_time_init=False):
|
|||||||
try:
|
try:
|
||||||
import pkg.utils.announcement as announcement
|
import pkg.utils.announcement as announcement
|
||||||
new_announcement = announcement.fetch_new()
|
new_announcement = announcement.fetch_new()
|
||||||
if new_announcement != "":
|
if len(new_announcement) > 0:
|
||||||
logging.critical("[公告] {}".format(new_announcement))
|
for announcement in new_announcement:
|
||||||
|
logging.critical("[公告]<{}> {}".format(announcement['time'], announcement['content']))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.warning("获取公告失败:{}".format(e))
|
logging.warning("获取公告失败:{}".format(e))
|
||||||
|
|
||||||
@@ -413,6 +369,11 @@ def check_file():
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
global use_override
|
||||||
|
# 检查是否携带了 --override 或 -r 参数
|
||||||
|
if '--override' in sys.argv or '-r' in sys.argv:
|
||||||
|
use_override = True
|
||||||
|
|
||||||
# 初始化相关文件
|
# 初始化相关文件
|
||||||
check_file()
|
check_file()
|
||||||
|
|
||||||
|
|||||||
@@ -60,15 +60,18 @@
|
|||||||
"show_prefix": false,
|
"show_prefix": false,
|
||||||
"blob_message_threshold": 256,
|
"blob_message_threshold": 256,
|
||||||
"blob_message_strategy": "forward",
|
"blob_message_strategy": "forward",
|
||||||
|
"wait_last_done": true,
|
||||||
"font_path": "",
|
"font_path": "",
|
||||||
"retry_times": 3,
|
"retry_times": 3,
|
||||||
"hide_exce_info_to_user": false,
|
"hide_exce_info_to_user": false,
|
||||||
"sys_pool_num": 8,
|
"sys_pool_num": 8,
|
||||||
"admin_pool_num": 2,
|
"admin_pool_num": 4,
|
||||||
"user_pool_num": 6,
|
"user_pool_num": 8,
|
||||||
"session_expire_time": 1200,
|
"session_expire_time": 1200,
|
||||||
"rate_limitation": 60,
|
"rate_limitation": {
|
||||||
"rate_limit_strategy": "wait",
|
"default": 60
|
||||||
|
},
|
||||||
|
"rate_limit_strategy": "drop",
|
||||||
"upgrade_dependencies": true,
|
"upgrade_dependencies": true,
|
||||||
"report_usage": true,
|
"report_usage": true,
|
||||||
"logging_level": 20
|
"logging_level": 20
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ class ModelRequest:
|
|||||||
self.error_info = "{}\n该错误可能是由于http_proxy格式设置错误引起的"
|
self.error_info = "{}\n该错误可能是由于http_proxy格式设置错误引起的"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.error_info = "{}\n由于请求异常产生的未知错误,请查看日志".format(e)
|
self.error_info = "{}\n由于请求异常产生的未知错误,请查看日志".format(e)
|
||||||
raise Exception(self.error_info)
|
raise type(e)(self.error_info)
|
||||||
|
|
||||||
def request(self, **kwargs):
|
def request(self, **kwargs):
|
||||||
"""向接口发起请求"""
|
"""向接口发起请求"""
|
||||||
|
|||||||
@@ -156,8 +156,8 @@ def install_plugin(repo_url: str):
|
|||||||
import pkg.utils.pkgmgr
|
import pkg.utils.pkgmgr
|
||||||
pkg.utils.pkgmgr.install_requirements("plugins/"+repo_url.split(".git")[0].split("/")[-1]+"/requirements.txt")
|
pkg.utils.pkgmgr.install_requirements("plugins/"+repo_url.split(".git")[0].split("/")[-1]+"/requirements.txt")
|
||||||
|
|
||||||
import main
|
import pkg.utils.log as log
|
||||||
main.reset_logging()
|
log.reset_logging()
|
||||||
|
|
||||||
|
|
||||||
def uninstall_plugin(plugin_name: str) -> str:
|
def uninstall_plugin(plugin_name: str) -> str:
|
||||||
|
|||||||
@@ -117,8 +117,8 @@ class PluginUpdateCommand(AbstractCommandNode):
|
|||||||
import pkg.utils.pkgmgr
|
import pkg.utils.pkgmgr
|
||||||
pkg.utils.pkgmgr.install_requirements("/".join(plugin['path'].split('/')[:-1])+"/requirements.txt")
|
pkg.utils.pkgmgr.install_requirements("/".join(plugin['path'].split('/')[:-1])+"/requirements.txt")
|
||||||
|
|
||||||
import main
|
import pkg.utils.log as log
|
||||||
main.reset_logging()
|
log.reset_logging()
|
||||||
|
|
||||||
pkg.utils.context.get_qqbot_manager().notify_admin("已更新插件: {}".format(", ".join(updated)))
|
pkg.utils.context.get_qqbot_manager().notify_admin("已更新插件: {}".format(", ".join(updated)))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -59,6 +59,11 @@ def process_message(launcher_type: str, launcher_id: int, text_message: str, mes
|
|||||||
logging.info("根据忽略规则忽略消息: {}".format(text_message))
|
logging.info("根据忽略规则忽略消息: {}".format(text_message))
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
import config
|
||||||
|
|
||||||
|
if not config.wait_last_done and session_name in processing:
|
||||||
|
return MessageChain([Plain(tips_custom.message_drop_tip)])
|
||||||
|
|
||||||
# 检查是否被禁言
|
# 检查是否被禁言
|
||||||
if launcher_type == 'group':
|
if launcher_type == 'group':
|
||||||
result = mgr.bot.member_info(target=launcher_id, member_id=mgr.bot.qq).get()
|
result = mgr.bot.member_info(target=launcher_id, member_id=mgr.bot.qq).get()
|
||||||
@@ -79,9 +84,6 @@ def process_message(launcher_type: str, launcher_id: int, text_message: str, mes
|
|||||||
|
|
||||||
# 处理消息
|
# 处理消息
|
||||||
try:
|
try:
|
||||||
if session_name in processing:
|
|
||||||
pkg.openai.session.get_session(session_name).release_response_lock()
|
|
||||||
return MessageChain([Plain("[bot]err:正在处理中,请稍后再试")])
|
|
||||||
|
|
||||||
config = pkg.utils.context.get_config()
|
config = pkg.utils.context.get_config()
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,20 @@ __crt_minute_usage__ = {}
|
|||||||
__timer_thr__: threading.Thread = None
|
__timer_thr__: threading.Thread = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_limitation(session_name: str) -> int:
|
||||||
|
"""获取会话的限制次数"""
|
||||||
|
import config
|
||||||
|
|
||||||
|
if type(config.rate_limitation) == dict:
|
||||||
|
# 如果被指定了
|
||||||
|
if session_name in config.rate_limitation:
|
||||||
|
return config.rate_limitation[session_name]
|
||||||
|
else:
|
||||||
|
return config.rate_limitation["default"]
|
||||||
|
elif type(config.rate_limitation) == int:
|
||||||
|
return config.rate_limitation
|
||||||
|
|
||||||
|
|
||||||
def add_usage(session_name: str):
|
def add_usage(session_name: str):
|
||||||
"""增加会话的对话次数"""
|
"""增加会话的对话次数"""
|
||||||
global __crt_minute_usage__
|
global __crt_minute_usage__
|
||||||
@@ -56,9 +70,7 @@ def get_rest_wait_time(session_name: str, spent: float) -> float:
|
|||||||
"""获取会话此回合的剩余等待时间"""
|
"""获取会话此回合的剩余等待时间"""
|
||||||
global __crt_minute_usage__
|
global __crt_minute_usage__
|
||||||
|
|
||||||
import config
|
min_seconds_per_round = 60.0 / get_limitation(session_name)
|
||||||
|
|
||||||
min_seconds_per_round = 60.0 / config.rate_limitation
|
|
||||||
|
|
||||||
if session_name in __crt_minute_usage__:
|
if session_name in __crt_minute_usage__:
|
||||||
return max(0, min_seconds_per_round - spent)
|
return max(0, min_seconds_per_round - spent)
|
||||||
@@ -70,10 +82,8 @@ def is_reach_limit(session_name: str) -> bool:
|
|||||||
"""判断会话是否超过限制"""
|
"""判断会话是否超过限制"""
|
||||||
global __crt_minute_usage__
|
global __crt_minute_usage__
|
||||||
|
|
||||||
import config
|
|
||||||
|
|
||||||
if session_name in __crt_minute_usage__:
|
if session_name in __crt_minute_usage__:
|
||||||
return __crt_minute_usage__[session_name] >= config.rate_limitation
|
return __crt_minute_usage__[session_name] >= get_limitation(session_name)
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -1,47 +1,68 @@
|
|||||||
import base64
|
import base64
|
||||||
import os
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
import pkg.utils.network as network
|
|
||||||
|
|
||||||
|
def read_latest() -> list:
|
||||||
def read_latest() -> str:
|
import pkg.utils.network as network
|
||||||
resp = requests.get(
|
resp = requests.get(
|
||||||
url="https://api.github.com/repos/RockChinQ/QChatGPT/contents/res/announcement",
|
url="https://api.github.com/repos/RockChinQ/QChatGPT/contents/res/announcement.json",
|
||||||
proxies=network.wrapper_proxies()
|
proxies=network.wrapper_proxies()
|
||||||
)
|
)
|
||||||
obj_json = resp.json()
|
obj_json = resp.json()
|
||||||
b64_content = obj_json["content"]
|
b64_content = obj_json["content"]
|
||||||
# 解码
|
# 解码
|
||||||
content = base64.b64decode(b64_content).decode("utf-8")
|
content = base64.b64decode(b64_content).decode("utf-8")
|
||||||
return content
|
return json.loads(content)
|
||||||
|
|
||||||
|
|
||||||
def read_saved() -> str:
|
def read_saved() -> list:
|
||||||
# 已保存的在res/announcement_saved
|
# 已保存的在res/announcement_saved
|
||||||
# 检查是否存在
|
# 检查是否存在
|
||||||
if not os.path.exists("res/announcement_saved"):
|
if not os.path.exists("res/announcement_saved.json"):
|
||||||
with open("res/announcement_saved", "w", encoding="utf-8") as f:
|
with open("res/announcement_saved.json", "w", encoding="utf-8") as f:
|
||||||
f.write("")
|
f.write("[]")
|
||||||
|
|
||||||
with open("res/announcement_saved", "r", encoding="utf-8") as f:
|
with open("res/announcement_saved.json", "r", encoding="utf-8") as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
|
|
||||||
return content
|
return json.loads(content)
|
||||||
|
|
||||||
|
|
||||||
def write_saved(content: str):
|
def write_saved(content: list):
|
||||||
# 已保存的在res/announcement_saved
|
# 已保存的在res/announcement_saved
|
||||||
with open("res/announcement_saved", "w", encoding="utf-8") as f:
|
with open("res/announcement_saved.json", "w", encoding="utf-8") as f:
|
||||||
f.write(content)
|
f.write(json.dumps(content, indent=4, ensure_ascii=False))
|
||||||
|
|
||||||
|
|
||||||
def fetch_new() -> str:
|
def fetch_new() -> list:
|
||||||
latest = read_latest()
|
latest = read_latest()
|
||||||
saved = read_saved()
|
saved = read_saved()
|
||||||
if latest.replace(saved, "").strip() == "":
|
|
||||||
return ""
|
to_show: list = []
|
||||||
else:
|
|
||||||
write_saved(latest)
|
for item in latest:
|
||||||
return latest.replace(saved, "").strip()
|
# 遍历saved检查是否有相同id的公告
|
||||||
|
for saved_item in saved:
|
||||||
|
if saved_item["id"] == item["id"]:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# 没有相同id的公告
|
||||||
|
to_show.append(item)
|
||||||
|
|
||||||
|
write_saved(latest)
|
||||||
|
return to_show
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
resp = requests.get(
|
||||||
|
url="https://api.github.com/repos/RockChinQ/QChatGPT/contents/res/announcement.json",
|
||||||
|
)
|
||||||
|
obj_json = resp.json()
|
||||||
|
b64_content = obj_json["content"]
|
||||||
|
# 解码
|
||||||
|
content = base64.b64decode(b64_content).decode("utf-8")
|
||||||
|
print(json.dumps(json.loads(content), indent=4, ensure_ascii=False))
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
66
pkg/utils/log.py
Normal file
66
pkg/utils/log.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import os
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
|
log_file_name = "qchatgpt.log"
|
||||||
|
|
||||||
|
|
||||||
|
log_colors_config = {
|
||||||
|
'DEBUG': 'green', # cyan white
|
||||||
|
'INFO': 'white',
|
||||||
|
'WARNING': 'yellow',
|
||||||
|
'ERROR': 'red',
|
||||||
|
'CRITICAL': 'cyan',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def init_runtime_log_file():
|
||||||
|
"""为此次运行生成日志文件
|
||||||
|
格式: qchatgpt-yyyy-MM-dd-HH-mm-ss.log
|
||||||
|
"""
|
||||||
|
global log_file_name
|
||||||
|
|
||||||
|
# 检查logs目录是否存在
|
||||||
|
if not os.path.exists("logs"):
|
||||||
|
os.mkdir("logs")
|
||||||
|
|
||||||
|
# 检查本目录是否有qchatgpt.log,若有,移动到logs目录
|
||||||
|
if os.path.exists("qchatgpt.log"):
|
||||||
|
shutil.move("qchatgpt.log", "logs/qchatgpt.legacy.log")
|
||||||
|
|
||||||
|
log_file_name = "logs/qchatgpt-%s.log" % time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
|
||||||
|
|
||||||
|
|
||||||
|
def reset_logging():
|
||||||
|
global log_file_name
|
||||||
|
|
||||||
|
import config
|
||||||
|
import pkg.utils.context
|
||||||
|
import colorlog
|
||||||
|
|
||||||
|
if pkg.utils.context.context['logger_handler'] is not None:
|
||||||
|
logging.getLogger().removeHandler(pkg.utils.context.context['logger_handler'])
|
||||||
|
|
||||||
|
for handler in logging.getLogger().handlers:
|
||||||
|
logging.getLogger().removeHandler(handler)
|
||||||
|
|
||||||
|
logging.basicConfig(level=config.logging_level, # 设置日志输出格式
|
||||||
|
filename=log_file_name, # log日志输出的文件位置和文件名
|
||||||
|
format="[%(asctime)s.%(msecs)03d] %(filename)s (%(lineno)d) - [%(levelname)s] : %(message)s",
|
||||||
|
# 日志输出的格式
|
||||||
|
# -8表示占位符,让输出左对齐,输出长度都为8位
|
||||||
|
datefmt="%Y-%m-%d %H:%M:%S" # 时间输出的格式
|
||||||
|
)
|
||||||
|
sh = logging.StreamHandler()
|
||||||
|
sh.setLevel(config.logging_level)
|
||||||
|
sh.setFormatter(colorlog.ColoredFormatter(
|
||||||
|
fmt="%(log_color)s[%(asctime)s.%(msecs)03d] %(filename)s (%(lineno)d) - [%(levelname)s] : "
|
||||||
|
"%(message)s",
|
||||||
|
datefmt="%Y-%m-%d %H:%M:%S",
|
||||||
|
log_colors=log_colors_config
|
||||||
|
))
|
||||||
|
logging.getLogger().addHandler(sh)
|
||||||
|
pkg.utils.context.context['logger_handler'] = sh
|
||||||
|
return sh
|
||||||
@@ -1,21 +1,25 @@
|
|||||||
from pip._internal import main as pipmain
|
from pip._internal import main as pipmain
|
||||||
|
|
||||||
import main
|
import pkg.utils.log as log
|
||||||
|
|
||||||
|
|
||||||
def install(package):
|
def install(package):
|
||||||
pipmain(['install', package])
|
pipmain(['install', package])
|
||||||
main.reset_logging()
|
log.reset_logging()
|
||||||
|
|
||||||
|
def install_upgrade(package):
|
||||||
|
pipmain(['install', '--upgrade', package])
|
||||||
|
log.reset_logging()
|
||||||
|
|
||||||
|
|
||||||
def run_pip(params: list):
|
def run_pip(params: list):
|
||||||
pipmain(params)
|
pipmain(params)
|
||||||
main.reset_logging()
|
log.reset_logging()
|
||||||
|
|
||||||
|
|
||||||
def install_requirements(file):
|
def install_requirements(file):
|
||||||
pipmain(['install', '-r', file, "--upgrade"])
|
pipmain(['install', '-r', file, "--upgrade"])
|
||||||
main.reset_logging()
|
log.reset_logging()
|
||||||
|
|
||||||
|
|
||||||
def ensure_dulwich():
|
def ensure_dulwich():
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
requests~=2.28.1
|
requests~=2.28.1
|
||||||
openai~=0.27.2
|
openai~=0.27.4
|
||||||
dulwich~=0.21.3
|
dulwich~=0.21.3
|
||||||
colorlog~=6.6.0
|
colorlog~=6.6.0
|
||||||
yiri-mirai~=0.2.6.1
|
yiri-mirai~=0.2.6.1
|
||||||
websockets~=10.4
|
websockets
|
||||||
urllib3~=1.26.10
|
urllib3~=1.26.10
|
||||||
func_timeout~=4.3.5
|
func_timeout~=4.3.5
|
||||||
Pillow
|
Pillow
|
||||||
1
res/announcement.json
Normal file
1
res/announcement.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[]
|
||||||
32
res/scripts/publish_announcement.py
Normal file
32
res/scripts/publish_announcement.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# 输出工作路径
|
||||||
|
import os
|
||||||
|
print("工作路径: " + os.getcwd())
|
||||||
|
announcement = input("请输入公告内容: ")
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
# 读取现有的公告文件 res/announcement.json
|
||||||
|
with open("res/announcement.json", "r", encoding="utf-8") as f:
|
||||||
|
announcement_json = json.load(f)
|
||||||
|
|
||||||
|
# 将公告内容写入公告文件
|
||||||
|
|
||||||
|
# 当前自然时间
|
||||||
|
import time
|
||||||
|
now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||||
|
|
||||||
|
# 获取最后一个公告的id
|
||||||
|
last_id = announcement_json[-1]["id"] if len(announcement_json) > 0 else -1
|
||||||
|
|
||||||
|
announcement = {
|
||||||
|
"id": last_id + 1,
|
||||||
|
"time": now,
|
||||||
|
"timestamp": int(time.time()),
|
||||||
|
"content": announcement
|
||||||
|
}
|
||||||
|
|
||||||
|
announcement_json.append(announcement)
|
||||||
|
|
||||||
|
# 将公告写入公告文件
|
||||||
|
with open("res/announcement.json", "w", encoding="utf-8") as f:
|
||||||
|
json.dump(announcement_json, f, indent=4, ensure_ascii=False)
|
||||||
@@ -9,9 +9,12 @@ alter_tip_message = '[bot]err:出错了,请稍后再试'
|
|||||||
# 若设置为空字符串,则不发送提示信息
|
# 若设置为空字符串,则不发送提示信息
|
||||||
rate_limit_drop_tip = "本分钟对话次数超过限速次数,此对话被丢弃"
|
rate_limit_drop_tip = "本分钟对话次数超过限速次数,此对话被丢弃"
|
||||||
|
|
||||||
|
# 只允许同时处理一条消息时,新消息被丢弃时的提示信息
|
||||||
|
# 当config.py中的wait_last_done为False时生效
|
||||||
|
# 若设置为空字符串,则不发送提示信息
|
||||||
|
message_drop_tip = "[bot]当前有一条消息正在处理,请等待处理完成"
|
||||||
|
|
||||||
# 指令!help帮助消息
|
# 指令!help帮助消息
|
||||||
# config.py,line:279
|
|
||||||
# pkg/qqbot/process.py,line:122
|
|
||||||
help_message = """此机器人通过调用大型语言模型生成回复,不具有情感。
|
help_message = """此机器人通过调用大型语言模型生成回复,不具有情感。
|
||||||
你可以用自然语言与其交流,回复的消息中[GPT]开头的为模型生成的语言,[bot]开头的为程序提示。
|
你可以用自然语言与其交流,回复的消息中[GPT]开头的为模型生成的语言,[bot]开头的为程序提示。
|
||||||
欢迎到github.com/RockChinQ/QChatGPT 给个star"""
|
欢迎到github.com/RockChinQ/QChatGPT 给个star"""
|
||||||
|
|||||||
Reference in New Issue
Block a user