mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-07-20 13:47:15 +08:00
plugin: add Role plugin
This commit is contained in:
122
plugins/role/role.py
Normal file
122
plugins/role/role.py
Normal file
@@ -0,0 +1,122 @@
|
||||
# encoding:utf-8
|
||||
|
||||
import json
|
||||
import os
|
||||
from bridge.bridge import Bridge
|
||||
from bridge.context import ContextType
|
||||
from bridge.reply import Reply, ReplyType
|
||||
import plugins
|
||||
from plugins import *
|
||||
from common.log import logger
|
||||
|
||||
|
||||
class RolePlay():
|
||||
def __init__(self, bot, sessionid, desc, wrapper=None):
|
||||
self.bot = bot
|
||||
self.sessionid = sessionid
|
||||
bot.sessions.clear_session(sessionid)
|
||||
bot.sessions.build_session(sessionid, desc)
|
||||
self.wrapper = wrapper or "%s" # 用于包装用户输入
|
||||
|
||||
def reset(self):
|
||||
self.bot.sessions.clear_session(self.sessionid)
|
||||
|
||||
def action(self, user_action):
|
||||
prompt = self.wrapper % user_action
|
||||
return prompt
|
||||
|
||||
@plugins.register(name="Role", desc="为你的Bot设置预设角色", version="1.0", author="lanvent", desire_priority= 0)
|
||||
class Role(Plugin):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
curdir = os.path.dirname(__file__)
|
||||
config_path = os.path.join(curdir, "roles.json")
|
||||
try:
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
config = json.load(f)
|
||||
self.roles = {role["title"].lower(): role for role in config["roles"]}
|
||||
if len(self.roles) == 0:
|
||||
raise Exception("no role found")
|
||||
self.handlers[Event.ON_HANDLE_CONTEXT] = self.on_handle_context
|
||||
self.roleplays = {}
|
||||
logger.info("[Role] inited")
|
||||
except FileNotFoundError:
|
||||
logger.error(f"[Role] init failed, {config_path} not found")
|
||||
except Exception as e:
|
||||
logger.error("[Role] init failed, exception: %s" % e)
|
||||
|
||||
def get_role(self, name, find_closest=True):
|
||||
name = name.lower()
|
||||
found_role = None
|
||||
if name in self.roles:
|
||||
found_role = name
|
||||
elif find_closest:
|
||||
import difflib
|
||||
|
||||
def str_simularity(a, b):
|
||||
return difflib.SequenceMatcher(None, a, b).ratio()
|
||||
max_sim = 0.0
|
||||
max_role = None
|
||||
for role in self.roles:
|
||||
sim = str_simularity(name, role)
|
||||
if sim >= max_sim:
|
||||
max_sim = sim
|
||||
max_role = role
|
||||
found_role = max_role
|
||||
return found_role
|
||||
|
||||
def on_handle_context(self, e_context: EventContext):
|
||||
|
||||
if e_context['context'].type != ContextType.TEXT:
|
||||
return
|
||||
bottype = Bridge().get_bot_type("chat")
|
||||
if bottype != "chatGPT":
|
||||
return
|
||||
bot = Bridge().get_bot("chat")
|
||||
content = e_context['context'].content[:]
|
||||
clist = e_context['context'].content.split(maxsplit=1)
|
||||
desckey = None
|
||||
sessionid = e_context['context']['session_id']
|
||||
if clist[0] == "$停止扮演":
|
||||
if sessionid in self.roleplays:
|
||||
self.roleplays[sessionid].reset()
|
||||
del self.roleplays[sessionid]
|
||||
reply = Reply(ReplyType.INFO, "角色扮演结束!")
|
||||
e_context['reply'] = reply
|
||||
e_context.action = EventAction.BREAK_PASS
|
||||
return
|
||||
elif clist[0] == "$角色":
|
||||
desckey = "descn"
|
||||
elif clist[0].lower() == "$role":
|
||||
desckey = "description"
|
||||
elif sessionid not in self.roleplays:
|
||||
return
|
||||
logger.debug("[Role] on_handle_context. content: %s" % content)
|
||||
if desckey is not None:
|
||||
if len(clist) == 1 or (len(clist) > 1 and clist[1].lower() in ["help", "帮助"]):
|
||||
reply = Reply(ReplyType.INFO, self.get_help_text())
|
||||
e_context['reply'] = reply
|
||||
e_context.action = EventAction.BREAK_PASS
|
||||
return
|
||||
role = self.get_role(clist[1])
|
||||
if role is None:
|
||||
reply = Reply(ReplyType.ERROR, "角色不存在")
|
||||
e_context['reply'] = reply
|
||||
e_context.action = EventAction.BREAK_PASS
|
||||
return
|
||||
else:
|
||||
self.roleplays[sessionid] = RolePlay(bot, sessionid, self.roles[role][desckey],self.roles[role].get("wrapper","%s"))
|
||||
reply = Reply(ReplyType.INFO, f"角色设定为 {role} :\n"+self.roles[role][desckey])
|
||||
e_context['reply'] = reply
|
||||
e_context.action = EventAction.BREAK_PASS
|
||||
else:
|
||||
prompt = self.roleplays[sessionid].action(content)
|
||||
e_context['context'].type = ContextType.TEXT
|
||||
e_context['context'].content = prompt
|
||||
e_context.action = EventAction.CONTINUE
|
||||
|
||||
def get_help_text(self):
|
||||
help_text = "输入\"$角色 (角色名)\"或\"$role (角色名)\"为我设定角色吧,#reset 可以清除设定的角色。\n目前可用角色列表:\n"
|
||||
for role in self.roles:
|
||||
help_text += f"[{role}]: {self.roles[role]['remark']}\n"
|
||||
return help_text
|
||||
Reference in New Issue
Block a user