Files
bot-on-anything/plugins/README.md

122 lines
5.9 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.
# 简介
**[chatgpt-on-wechat](https://github.com/zhayujie/chatgpt-on-wechat/tree/master/plugins)** 插件的思路对 **bot-on-anything** 进行插件化,期望能实现插件的共享使用,但是由于两个项目的架构存在较大差异,只能尽最大可能兼容 **[chatgpt-on-wechat](https://github.com/zhayujie/chatgpt-on-wechat/tree/master/plugins)** 的插件,部分功能还需进行适配。
## **插件监听的事件:**
事件顺序为 1、ON_HANDLE_CONTEXT --> 2、ON_BRIDGE_HANDLE_CONTEXT(ON_BRIDGE_HANDLE_STREAM_CONTEXT) --> 3、ON_DECORATE_REPLY
触发事件会产生事件的上下文EventContext它可能包含了以下信息:
EventContext(Event事件类型, {'channel' : 本次消息的context, 'context': 本次消息用户的提问, 'reply': 当前AI回复, "args": 其他上下文参数})
插件处理函数可通过修改EventContext中的context、reply、args或者调用channel中对应的方法来实现功能。
```
class Event(Enum):
ON_HANDLE_CONTEXT = 2 # 对应通道处理消息前
"""
e_context = { "channel": 消息channel, "context" : 本次消息的context, "reply" : 目前的回复,初始为空 , "args": 其他上下文参数 }
"""
ON_DECORATE_REPLY = 3 # 得到回复后准备装饰
"""
e_context = { "channel": 消息channel, "context" : 本次消息的context, "reply" : 目前的回复 , "args": 其他上下文参数 }
"""
ON_SEND_REPLY = 4 # 发送回复前
"""
bot-on-anything 不支持ON_SEND_REPLY事件,请使用ON_BRIDGE_HANDLE_CONTEXT或者ON_BRIDGE_HANDLE_STREAM_CONTEXT事件
"""
ON_BRIDGE_HANDLE_CONTEXT = 6 # 模型桥处理消息前
"""
e_context = { "context" : 本次消息的context, "reply" : 目前的回复,初始为空 , "args": 其他上下文参数 , 模型桥会调用args.model指定的AI模型来进行回复 }
"""
ON_BRIDGE_HANDLE_STREAM_CONTEXT = 7 # 模型桥处理流式消息前,流式对话的消息处理仅支持一次性返回,请直接返回结果
"""
e_context = { "context" : 本次消息的context, "reply" : 目前的回复,初始为空 , "args": 其他上下文参数 , 模型桥会调用args.model指定的AI模型来进行回复 }
"""
```
## 插件编写示例
`plugins/selector`为例,其中编写了一个通过判断前缀调用不同模型的`Selector`插件。
### 1. 创建插件
`plugins`目录下创建一个插件文件夹`selector`。然后,在该文件夹中创建同名``selector.py``文件。
```
plugins/
└── selector
└── selector.py
```
### 2. 编写功能
在`selector.py`文件中,创建插件类`Selector`,它继承自`Plugin`。
在类定义之前需要使用`@plugins.register`装饰器注册插件,并填写插件的相关信息,其中`desire_priority`表示插件默认的优先级,越大优先级越高。`Selector`插件加载时读取了同目录下的`selector.json`文件,从中取出对应的模型和触发前缀,`Selector`插件为事件`ON_HANDLE_CONTEXT`和`ON_BRIDGE_HANDLE_STREAM_CONTEXT`绑定了一个处理函数`select_model`,它表示在模型桥调用指定模型之前,都会先由`select_model`函数预处理。
```python
@plugins.register(name="Selector", desire_priority=99, hidden=True, desc="A model selector", version="0.1", author="RegimenArsenic")
class Selector(Plugin):
def __init__(self):
super().__init__()
curdir = os.path.dirname(__file__)
try:
self.config = functions.load_json_file(curdir, "selector.json")
except Exception as e:
log.warn("[Selector] init failed")
raise e
self.handlers[Event.ON_HANDLE_CONTEXT] = self.select_model
self.handlers[Event.ON_BRIDGE_HANDLE_STREAM_CONTEXT] = self.select_model
log.info("[Selector] inited")
```
### 3. 编写事件处理函数
#### 修改事件上下文
事件处理函数接收一个`EventContext`对象`e_context`作为参数。`e_context`包含了事件相关信息,利用`e_context['key']`来访问这些信息。
`EventContext(Event事件类型, {'channel' : 消息channel, 'context': Context, 'reply': Reply , "args": 其他上下文参数})`
处理函数中通过修改`e_context`对象中的事件相关信息来实现所需功能,比如更改`e_context['reply']`中的内容可以修改回复,更改`e_context['context']`中的内容可以修改用户提问。
#### 决定是否交付给下个插件或默认逻辑
在处理函数结束时,还需要设置`e_context`对象的`action`属性,它决定如何继续处理事件。目前有以下三种处理方式:
- `EventAction.CONTINUE`: 事件未结束,继续交给下个插件处理,如果没有下个插件,则交付给默认的事件处理逻辑。
- `EventAction.BREAK`: 事件结束,不再给下个插件处理,交付给默认的处理逻辑。
- `EventAction.BREAK_PASS`: 事件结束,不再给下个插件处理,跳过默认的处理逻辑。
#### 示例处理函数
`Selector`插件通过判断前缀,如有`@bing`前缀,则修改调用模型为bing模型若前缀为`@gpt`则修改调用模型为chatgpt否则就使用app里配置的原始模型插件同时删去提问的前缀`@bing`或者`@gpt`
```python
def select_model(self, e_context: EventContext):
model=e_context['args'].get('model')
for selector in self.config.get("selector", []):
prefix = selector.get('prefix', [])
check_prefix=functions.check_prefix(e_context["context"], prefix)
if (check_prefix):
model=selector.get('model')
if isinstance(check_prefix, str):
e_context["context"] = e_context["context"].split(check_prefix, 1)[1].strip()
break
log.debug(f"[Selector] select model {model}")
e_context.action = EventAction.CONTINUE # 事件继续,交付给下个插件或默认逻辑
e_context['args']['model']=model
return e_context
```