You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. # encoding:utf-8
  2. import json
  3. import os
  4. from bridge.bridge import Bridge
  5. from bridge.context import ContextType
  6. from bridge.reply import Reply, ReplyType
  7. import plugins
  8. from plugins import *
  9. from common.log import logger
  10. class RolePlay():
  11. def __init__(self, bot, sessionid, desc, wrapper=None):
  12. self.bot = bot
  13. self.sessionid = sessionid
  14. self.wrapper = wrapper or "%s" # 用于包装用户输入
  15. self.desc = desc
  16. def reset(self):
  17. self.bot.sessions.clear_session(self.sessionid)
  18. def action(self, user_action):
  19. session = self.bot.sessions.build_session(self.sessionid, self.desc)
  20. if session[0]['role'] == 'system' and session[0]['content'] != self.desc: # 目前没有触发session过期事件,这里先简单判断,然后重置
  21. self.reset()
  22. self.bot.sessions.build_session(self.sessionid, self.desc)
  23. prompt = self.wrapper % user_action
  24. return prompt
  25. @plugins.register(name="Role", desc="为你的Bot设置预设角色", version="1.0", author="lanvent", desire_priority= 0)
  26. class Role(Plugin):
  27. def __init__(self):
  28. super().__init__()
  29. curdir = os.path.dirname(__file__)
  30. config_path = os.path.join(curdir, "roles.json")
  31. try:
  32. with open(config_path, "r", encoding="utf-8") as f:
  33. config = json.load(f)
  34. self.roles = {role["title"].lower(): role for role in config["roles"]}
  35. if len(self.roles) == 0:
  36. raise Exception("no role found")
  37. self.handlers[Event.ON_HANDLE_CONTEXT] = self.on_handle_context
  38. self.roleplays = {}
  39. logger.info("[Role] inited")
  40. except FileNotFoundError:
  41. logger.error(f"[Role] init failed, {config_path} not found")
  42. except Exception as e:
  43. logger.error("[Role] init failed, exception: %s" % e)
  44. def get_role(self, name, find_closest=True):
  45. name = name.lower()
  46. found_role = None
  47. if name in self.roles:
  48. found_role = name
  49. elif find_closest:
  50. import difflib
  51. def str_simularity(a, b):
  52. return difflib.SequenceMatcher(None, a, b).ratio()
  53. max_sim = 0.0
  54. max_role = None
  55. for role in self.roles:
  56. sim = str_simularity(name, role)
  57. if sim >= max_sim:
  58. max_sim = sim
  59. max_role = role
  60. found_role = max_role
  61. return found_role
  62. def on_handle_context(self, e_context: EventContext):
  63. if e_context['context'].type != ContextType.TEXT:
  64. return
  65. bottype = Bridge().get_bot_type("chat")
  66. if bottype != "chatGPT":
  67. return
  68. bot = Bridge().get_bot("chat")
  69. content = e_context['context'].content[:]
  70. clist = e_context['context'].content.split(maxsplit=1)
  71. desckey = None
  72. sessionid = e_context['context']['session_id']
  73. if clist[0] == "$停止扮演":
  74. if sessionid in self.roleplays:
  75. self.roleplays[sessionid].reset()
  76. del self.roleplays[sessionid]
  77. reply = Reply(ReplyType.INFO, "角色扮演结束!")
  78. e_context['reply'] = reply
  79. e_context.action = EventAction.BREAK_PASS
  80. return
  81. elif clist[0] == "$角色":
  82. desckey = "descn"
  83. elif clist[0].lower() == "$role":
  84. desckey = "description"
  85. elif sessionid not in self.roleplays:
  86. return
  87. logger.debug("[Role] on_handle_context. content: %s" % content)
  88. if desckey is not None:
  89. if len(clist) == 1 or (len(clist) > 1 and clist[1].lower() in ["help", "帮助"]):
  90. reply = Reply(ReplyType.INFO, self.get_help_text())
  91. e_context['reply'] = reply
  92. e_context.action = EventAction.BREAK_PASS
  93. return
  94. role = self.get_role(clist[1])
  95. if role is None:
  96. reply = Reply(ReplyType.ERROR, "角色不存在")
  97. e_context['reply'] = reply
  98. e_context.action = EventAction.BREAK_PASS
  99. return
  100. else:
  101. self.roleplays[sessionid] = RolePlay(bot, sessionid, self.roles[role][desckey], self.roles[role].get("wrapper","%s"))
  102. reply = Reply(ReplyType.INFO, f"角色设定为 {role} :\n"+self.roles[role][desckey])
  103. e_context['reply'] = reply
  104. e_context.action = EventAction.BREAK_PASS
  105. else:
  106. prompt = self.roleplays[sessionid].action(content)
  107. e_context['context'].type = ContextType.TEXT
  108. e_context['context'].content = prompt
  109. e_context.action = EventAction.CONTINUE
  110. def get_help_text(self):
  111. help_text = "输入\"$角色 (角色名)\"或\"$role (角色名)\"为我设定角色吧,#reset 可以清除设定的角色。\n\n目前可用角色列表:\n"
  112. for role in self.roles:
  113. help_text += f"[{role}]: {self.roles[role]['remark']}\n"
  114. return help_text