Procházet zdrojové kódy

Merge pull request #568 from lanvent/dev

Fix: merge plugins to dev
master
zhayujie GitHub před 1 rokem
rodič
revize
f791c7eafd
V databázi nebyl nalezen žádný známý klíč pro tento podpis ID GPG klíče: 4AEE18F83AFDEB23
11 změnil soubory, kde provedl 85 přidání a 37 odebrání
  1. +1
    -1
      bot/chatgpt/chat_gpt_bot.py
  2. +5
    -9
      bridge/bridge.py
  3. +7
    -5
      channel/terminal/terminal_channel.py
  4. +7
    -6
      channel/wechat/wechat_channel.py
  5. +3
    -3
      channel/wechat/wechaty_channel.py
  6. +19
    -1
      common/expired_dict.py
  7. +3
    -3
      plugins/README.md
  8. +2
    -1
      plugins/dungeon/dungeon.py
  9. +3
    -2
      plugins/godcmd/godcmd.py
  10. +3
    -2
      plugins/role/role.py
  11. +32
    -4
      plugins/role/roles.json

+ 1
- 1
bot/chatgpt/chat_gpt_bot.py Zobrazit soubor

@@ -127,7 +127,7 @@ class ChatGPTBot(Bot):
def create_img(self, query, retry_count=0):
try:
if conf().get('rate_limit_dalle') and not self.tb4dalle.get_token():
return "请求太快了,请休息一下再问我吧"
return False, "请求太快了,请休息一下再问我吧"
logger.info("[OPEN_AI] image_query={}".format(query))
response = openai.Image.create(
prompt=query, #图片描述


+ 5
- 9
bridge/bridge.py Zobrazit soubor

@@ -12,13 +12,15 @@ from common import const
class Bridge(object):
def __init__(self):
self.btype={
"chat": "chatGPT",
"chat": const.CHATGPT,
"voice_to_text": "openai",
"text_to_voice": "baidu"
}
model_type = conf().get("model")
if model_type in ["text-davinci-003"]:
self.btype['chat'] = const.OPEN_AI
self.bots={}


def get_bot(self,typename):
if self.bots.get(typename) is None:
logger.info("create bot {} for {}".format(self.btype[typename],typename))
@@ -35,13 +37,7 @@ class Bridge(object):


def fetch_reply_content(self, query, context : Context) -> Reply:
bot_type = const.CHATGPT
model_type = conf().get("model")
if model_type in ["gpt-3.5-turbo", "gpt-4", "gpt-4-32k"]:
bot_type = const.CHATGPT
elif model_type in ["text-davinci-003"]:
bot_type = const.OPEN_AI
return bot_factory.create_bot(bot_type).reply(query, context)
return self.get_bot("chat").reply(query, context)


def fetch_voice_to_text(self, voiceFile) -> Reply:


+ 7
- 5
channel/terminal/terminal_channel.py Zobrazit soubor

@@ -1,9 +1,10 @@
from bridge.context import *
from channel.channel import Channel
import sys

class TerminalChannel(Channel):
def startup(self):
context = {"from_user_id": "User"}
context = Context()
print("\nPlease input your question")
while True:
try:
@@ -12,12 +13,13 @@ class TerminalChannel(Channel):
print("\nExiting...")
sys.exit()

context.type = ContextType.TEXT
context['session_id'] = "User"
context.content = prompt
print("Bot:")
sys.stdout.flush()
for res in super().build_reply_content(prompt, context):
print(res, end="")
sys.stdout.flush()
print("\n")
res = super().build_reply_content(prompt, context).content
print(res)


def get_input(self, prompt):


+ 7
- 6
channel/wechat/wechat_channel.py Zobrazit soubor

@@ -56,14 +56,15 @@ class WechatChannel(Channel):
# start message listener
itchat.run()

# handle_* 系列函数处理收到的消息后构造context,然后调用handle函数处理context
# context是一个字典,包含了消息的所有信息,包括以下key
# handle_* 系列函数处理收到的消息后构造Context,然后传入handle函数中处理Context和发送回复
# Context包含了消息的所有信息,包括以下属性
# type 消息类型, 包括TEXT、VOICE、IMAGE_CREATE
# content 消息内容,如果是TEXT类型,content就是文本内容,如果是VOICE类型,content就是语音文件名,如果是IMAGE_CREATE类型,content就是图片生成命令
# session_id: 会话id
# isgroup: 是否是群聊
# msg: 原始消息对象
# receiver: 需要回复的对象
# kwargs 附加参数字典,包含以下的key:
# session_id: 会话id
# isgroup: 是否是群聊
# receiver: 需要回复的对象
# msg: itchat的原始消息对象

def handle_voice(self, msg):
if conf().get('speech_recognition') != True:


+ 3
- 3
channel/wechat/wechaty_channel.py Zobrazit soubor

@@ -194,12 +194,12 @@ class WechatyChannel(Channel):
try:
if not query:
return
context = dict()
context = Context(ContextType.TEXT, query)
context['session_id'] = reply_user_id
reply_text = super().build_reply_content(query, context)
reply_text = super().build_reply_content(query, context).content
if reply_text:
# 转换 mp3 文件为 silk 格式
mp3_file = super().build_text_to_voice(reply_text)
mp3_file = super().build_text_to_voice(reply_text).content
silk_file = mp3_file.replace(".mp3", ".silk")
# Load the MP3 file
audio = AudioSegment.from_file(mp3_file, format="mp3")


+ 19
- 1
common/expired_dict.py Zobrazit soubor

@@ -16,8 +16,26 @@ class ExpiredDict(dict):
def __setitem__(self, key, value):
expiry_time = datetime.now() + timedelta(seconds=self.expires_in_seconds)
super().__setitem__(key, (value, expiry_time))

def get(self, key, default=None):
try:
return self[key]
except KeyError:
return default
return default
def __contains__(self, key):
try:
self[key]
return True
except KeyError:
return False
def keys(self):
keys=list(super().keys())
return [key for key in keys if key in self]
def items(self):
return [(key, self[key]) for key in self.keys()]
def __iter__(self):
return self.keys().__iter__()

+ 3
- 3
plugins/README.md Zobrazit soubor

@@ -31,7 +31,7 @@
context.kwargs = {'isgroup': False, 'msg': msg, 'receiver': other_user_id, 'session_id': other_user_id}
```
2. 产生回复
本过程用于处理消息。目前默认处理逻辑是根据`Context`的类型交付给对应的bot:
本过程用于处理消息。目前默认处理逻辑如下,它根据`Context`的类型交付给对应的bot。如果本过程未产生任何回复,则会跳过之后的处理阶段。
```python
if context.type == ContextType.TEXT or context.type == ContextType.IMAGE_CREATE:
reply = super().build_reply_content(context.content, context) #文字跟画图交付给chatgpt
@@ -133,9 +133,9 @@ class Hello(Plugin):
- `EventAction.BREAK`: 事件结束,不再给下个插件处理,交付给默认的处理逻辑。
- `EventAction.BREAK_PASS`: 事件结束,不再给下个插件处理,跳过默认的处理逻辑。

以`Hello`插件为例,它处理`Context`类型为`TEXT`的消息
以`Hello`插件为例,它处理`Context`类型为`TEXT`的消息
- 如果内容是`Hello`,直接将回复设置为`Hello+用户昵称`,并跳过之后的插件和默认逻辑。
- 如果内容是`End`,它会将`Context`的类型更改为`IMAGE_CREATE`,并让事件继续,如果最终交付到默认逻辑,会调用默认的画图Bot。
- 如果内容是`End`,它会将`Context`的类型更改为`IMAGE_CREATE`,并让事件继续,如果最终交付到默认逻辑,会调用默认的画图Bot来画画
```python
def on_handle_context(self, e_context: EventContext):
if e_context['context'].type != ContextType.TEXT:


+ 2
- 1
plugins/dungeon/dungeon.py Zobrazit soubor

@@ -8,6 +8,7 @@ from config import conf
import plugins
from plugins import *
from common.log import logger
from common import const

# https://github.com/bupticybee/ChineseAiDungeonChatGPT
class StoryTeller():
@@ -51,7 +52,7 @@ class Dungeon(Plugin):
if e_context['context'].type != ContextType.TEXT:
return
bottype = Bridge().get_bot_type("chat")
if bottype != "chatGPT":
if bottype != const.CHATGPT:
return
bot = Bridge().get_bot("chat")
content = e_context['context'].content[:]


+ 3
- 2
plugins/godcmd/godcmd.py Zobrazit soubor

@@ -10,6 +10,7 @@ from bridge.reply import Reply, ReplyType
from config import load_config
import plugins
from plugins import *
from common import const
from common.log import logger

# 定义指令集
@@ -163,7 +164,7 @@ class Godcmd(Plugin):
elif cmd == "id":
ok, result = True, f"用户id=\n{user}"
elif cmd == "reset":
if bottype == "chatGPT":
if bottype == const.CHATGPT:
bot.sessions.clear_session(session_id)
ok, result = True, "会话已重置"
else:
@@ -185,7 +186,7 @@ class Godcmd(Plugin):
load_config()
ok, result = True, "配置已重载"
elif cmd == "resetall":
if bottype == "chatGPT":
if bottype == const.CHATGPT:
bot.sessions.clear_all_session()
ok, result = True, "重置所有会话成功"
else:


+ 3
- 2
plugins/role/role.py Zobrazit soubor

@@ -5,6 +5,7 @@ import os
from bridge.bridge import Bridge
from bridge.context import ContextType
from bridge.reply import Reply, ReplyType
from common import const
import plugins
from plugins import *
from common.log import logger
@@ -73,7 +74,7 @@ class Role(Plugin):
if e_context['context'].type != ContextType.TEXT:
return
bottype = Bridge().get_bot_type("chat")
if bottype != "chatGPT":
if bottype != const.CHATGPT:
return
bot = Bridge().get_bot("chat")
content = e_context['context'].content[:]
@@ -119,7 +120,7 @@ class Role(Plugin):
e_context.action = EventAction.CONTINUE

def get_help_text(self):
help_text = "输入\"$角色 (角色名)\"或\"$role (角色名)\"为我设定角色吧,#reset 可以清除设定的角色。\n\n目前可用角色列表:\n"
help_text = "输入\"$角色 (角色名)\"或\"$role (角色名)\"为我设定角色吧,\"$停止扮演 \" 可以清除设定的角色。\n\n目前可用角色列表:\n"
for role in self.roles:
help_text += f"[{role}]: {self.roles[role]['remark']}\n"
return help_text

+ 32
- 4
plugins/role/roles.json Zobrazit soubor

@@ -4,7 +4,7 @@
"title": "英语翻译或修改",
"description": "I want you to act as an English translator, spelling corrector and improver. I will speak to you in any language and you will detect the language, translate it and answer in the corrected and improved version of my text, in English. I want you to replace my simplified A0-level words and sentences with more beautiful and elegant, upper level English words and sentences. Keep the meaning same, but make them more literary. I want you to only reply the correction, the improvements and nothing else, do not write explanations. Please treat every message I send later as text content",
"descn": "我希望你能充当英语翻译、拼写纠正者和改进者。我将用任何语言与你交谈,你将检测语言,翻译它,并在我的文本的更正和改进版本中用英语回答。我希望你用更漂亮、更优雅、更高级的英语单词和句子来取代我的简化 A0 级单词和句子。保持意思不变,但让它们更有文学性。我希望你只回答更正,改进,而不是其他,不要写解释。请把我之后的每一条消息都当作文本内容。",
"wrapper": "内容是:\n\"%s\"",
"wrapper": "你要翻译或纠正的内容是:\n\"%s\"",
"remark": "将其他语言翻译成英文,或改进你提供的英文句子。"
},
{
@@ -142,10 +142,10 @@
},
{
"title": "阴阳怪气语录生成器",
"description": "我希望你充当一个讽刺性阴阳怪气语录生成器。当我给你一个主题时,你需要为我提供一个讽刺性的、带有阴阳怪气的短语或句子来反驳该主题。这些短语或句子应该是幽默、机智且具有讽刺意味的。不要提供相关主题的普通或无趣的表述。",
"descn": "我希望你充当一个讽刺性阴阳怪气语录生成器。当我给你一个主题时,你需要为我提供一个讽刺性的、带有阴阳怪气的短语或句子来反驳该主题。这些短语或句子应该是幽默、机智且具有讽刺意味的。不要提供相关主题的普通或无趣的表述。",
"description": "我希望你充当一个阴阳怪气讽刺语录生成器。当我给你一个主题时,你需要使用阴阳怪气的语气来评价该主题,评价的思路是挖苦和讽刺。如果有该主题的反例更好(比如失败经历,糟糕体验。注意不要直接说那些糟糕体验,而是通过反讽、幽默的类比等方式来说明)。",
"descn": "我希望你充当一个阴阳怪气讽刺语录生成器。当我给你一个主题时,你需要使用阴阳怪气的语气来评价该主题,评价的思路是挖苦和讽刺。如果有该主题的反例更好(比如失败经历,糟糕体验。注意不要直接说那些糟糕体验,而是通过反讽、幽默的类比等方式来说明)。",
"wrapper": "主题是:\n\"%s\"",
"remark": "根据主题生成阴阳怪气语录。"
"remark": "根据主题生成阴阳怪气讽刺语录。"
},
{
"title": "舔狗语录生成器",
@@ -153,6 +153,34 @@
"descn": "我希望你充当一个舔狗语录生成器,为我提供不同场景下的甜言蜜语。请根据提供的状态生成一句适当的舔狗语录,让女神感受到我的关心和温柔,给女神做牛做马。不需要提供背景解释,只需提供根据场景生成的舔狗语录。",
"wrapper": "场景是:\n\"%s\"",
"remark": "根据场景生成舔狗语录。"
},
{
"title": "群聊取名",
"description": "我希望你充当微信群聊的命名专家。根据我提供的信息和背景,为这个群聊起几个有趣顺口且贴切的名字,每个不要超过8个字。请在回答中仅给出群聊名称,不要写任何额外的解释。",
"descn": "我希望你充当微信群聊的命名专家。根据我提供的信息和背景,为这个群聊起几个有趣顺口且贴切的名字,每个不要超过8个字。请在回答中仅给出群聊名称,不要写任何额外的解释。",
"wrapper": "信息和背景是:\n\"%s\"",
"remark": "根据给出的信息和背景为群聊取名。"
},
{
"title": "表情符号翻译器",
"description": "I want you to translate the sentences I wrote into emojis. I will write the sentence, and you will express it with emojis. I just want you to express it with emojis. I don't want you to reply with anything but emoji. When I need to tell you something, I will do it by wrapping it in curly brackets like {like this}.",
"descn": "我想让你把我写的句子翻译成表情符号。我写句子,你就用表情符号来表达。你只能用 emojis 来表达,除了表情符号不能使用任何文字。当我需要告诉你一些事情的时候,我会用大括号把它包起来,比如{像这样}。",
"wrapper": "需要翻译成表情符号的内容是:\n\"%s\"",
"remark": "将输入文字翻译为表情符号。"
},
{
"title": "AI 医生",
"description": "I want you to act as an AI assisted doctor. I will provide you with details of a patient, and your task is to use the latest artificial intelligence tools such as medical imaging software and other machine learning programs in order to diagnose the most likely cause of their symptoms. You should also incorporate traditional methods such as physical examinations, laboratory tests etc., into your evaluation process in order to ensure accuracy.",
"descn": "我想让你充当一名人工智能辅助的医生。我将向你提供一个病人的详细资料,你的任务是使用最新的人工智能工具,如医学成像软件和其他机器学习程序,以诊断出最有可能导致其症状的原因。你还应将传统方法,如体检、实验室测试等,纳入你的评估过程,以确保准确性。",
"wrapper": "需要诊断的资料是:\n\"%s\"",
"remark": "辅助诊断"
},
{
"title": "知识点阐述",
"description": "我会给予你词语,请你按照我给的词构建一个知识文字世界,你是此世界的导游,在世界里一切知识都是以象征的形式表达的,你在描述经历时应当适当加入五感的描述",
"descn": "我会给予你词语,请你按照我给的词构建一个知识文字世界,你是此世界的导游,在世界里一切知识都是以象征的形式表达的,你在描述经历时应当适当加入五感的描述",
"wrapper": "词语是:\n\"%s\"",
"remark": "用比喻的方式解释词语。"
}
]
}

Načítá se…
Zrušit
Uložit