QChatGPT/res/wiki/技术信息.md
2023-04-24 19:53:20 +08:00

108 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

以下是QChatGPT实现原理等技术信息贡献之前请仔细阅读
> 太久没更了,过时了,建议读源码,~~注释还挺全的~~
> 请先阅读OpenAI API的相关文档 https://beta.openai.com/docs/ 以下信息假定您已了解OpenAI模型的相关特性及其接口的调用方法。
## 术语
包含OpenAI API涉及的术语和项目中的概念的命名
括号中是程序中相应术语的命名,无括号的为抽象概念
### 模型(model)
AI模型程序调用OpenAI的接口获取的内容均为OpenAI的模型生成的内容。
### 字符(tokens)
OpenAI定义的字符ASCII字符为1 token其他为2 token。
### 提示符(prompt)
i. 调用OpenAI的文字补全模型时的提示语模型接口会根据提示语返回回复内容。程序底层会将对话内容进行封装生成提示符。调用文字补全模型时的提示符均由`user_name`(默认为`You`,可在配置文件修改)和`bot_name`(默认为`Bot`,可在配置文件修改)标记对话角色以供模型识别,以下是实例:
```
You:今天天气真不错
Bot:很高兴你喜欢今天的天气:)
You:谢谢你
Bot:不客气:)
```
补全模型调用的程序实现请查看下文`实现`节。
ii. 调用OpenAI的绘图模型时的提示语模型会根据提示语进行绘图并返回图片URL。
### 对象
程序将单个人或单个QQ群视为一个对象对象和模型是一次会话中的对话双方。
### 会话(session)
会话只对文字补全功能有效,绘图功能无会话概念。每个对象使用同一个会话,会话中仅有对象和模型两个角色,故群内所有的人都将被视为同一个角色与模型进行对话。
程序获取回复的本质是`文字补全`。
由于对话需要实现联系上下文,故程序会将模型与对象的对话历史记录作为`提示符`发送给OpenAI的接口以获取符合前文的回复。
而OpenAI的文字补全接口的提示符具有长度限制(默认使用的`text-davinci-003`限制为4096 tokens)
所以增加`会话`概念以管理向接口发送的提示符内容。
会话的存活时间可以在`config.py`中设置默认为20分钟。会话过期之后会被存入数据库并重置。下一次该对象发起对话时将重启新的会话。
### 预设值、人格(default_prompt)
每个会话的预设对话信息,可在`config.py`中设置,程序会在每个会话创建时向提示符写入以下内容:
```
You:<预设信息>
Bot:好的
```
## 实现
### QQ机器人
> 程序路径:
> pkg.qqbot
- `pkg.qqbot.manager`中的`QQBotManager`实现了接收消息、调用OpenAI模块处理消息、报告审计模块记录使用量等功能并提供通知管理员、发送消息等方法供其他模块调用。
- `pkg.qqbot.filter`提供了敏感词过滤的相关操作。
- `pkg.qqbot.process`提供了私聊消息和群聊消息的统一处理逻辑。
使用mirai及YiriMirai作为Python与QQ交互的框架详细请见其文档。
在启动时会调用YiriMirai的函数以创建一个bot对象用于程序通过mirai与QQ进行交互在上层程序调用此bot对象的方法进行消息处理。
由于YiriMirai暂时无法关闭机器人故在热重载前后维持同一个bot对象这意味着QQ机器人的相关配置(QQ号、适配器等)信息不支持热重载。
### 数据库
> 程序路径:
> pkg.database
- `pkg.database.manager`中的`DatabaseManager`封装了诸多调用数据库的方法以供其他模块调用。
使用SQLite作为数据库储存所有对象的历史会话信息、api-key的费用情况、api-key的使用量情况。
### OpenAI交互
> 程序路径:
> pkg.openai
- `pkg.openai.manager`中的`OpenAIInteract`类封装了OpenAI的文字补全`Completion`API和绘图API供机器人模块调用并在接口调用成功之后向审计模块报告当前使用的api-key的使用量信息。
- `pkg.openai.keymgr`实现了多api-key的管理其中以`exceeded`变量在运行时记录api-key的超额报错记录并提供根据超额记录进行的api-key切换功能。
- `pkg.openai.pricing`记录各个模型的费用信息供调用接口时估算费用费用估算功能不再与api-key的切换挂钩api-key仅在调用接口报错超额时进行切换。
- `pkg.openai.session`中的`Session`进行会话管理。
### utils模块
#### context模块
保存前述模块中的对象,并允许各个模块从此处获取其他模块的对象以调用其方法。
#### 热重载功能
> pkg.utils.reloader
重载前保存context中的所有对象执行`main.py`中的程序关闭流程,使用`importlib`的`reload`函数重载所有模块(包含配置文件,包含新增的模块)重载后将context恢复并执行程序启动流程。
所有模块都会重新创建对象但QQ机器人模块中的bot对象不会被重新创建这是因为YiriMirai提供的shutdown方法无法使用这意味着`config.py`中关于QQ机器人的配置不支持热重载。
#### 热更新功能
> pkg.utils.updater
使用`dulwich`库执行pull操作拉取远程仓库的最新源码并进行一次热重载加载最新代码。