perf: 插件报错直接终止事件;支持生成器发送信息

This commit is contained in:
Soulter
2024-12-14 20:11:28 +08:00
parent d58b9edf78
commit 3a67492680
3 changed files with 53 additions and 13 deletions
@@ -6,6 +6,8 @@ from astrbot.core.message.message_event_result import MessageEventResult, Comman
from astrbot.core import logger
from astrbot.core.star.star_handler import StarHandlerMetadata
from astrbot.core.star.star import star_map
import traceback
import inspect
class StarRequestSubStage(Stage):
async def initialize(self, ctx: PipelineContext) -> None:
@@ -28,23 +30,53 @@ class StarRequestSubStage(Stage):
star_cls_obj = star_map.get(handler.handler_module_str).star_cls
# 判断 handler 是否是类方法(通过装饰器注册的没有 __self__ 属性)
ready_to_call = None
if hasattr(handler.handler, '__self__'):
# 猜测没有通过装饰器去注册
try:
ret = await handler.handler(event, **params)
ready_to_call = handler.handler(event, **params)
except TypeError:
# 向下兼容
ret = await handler.handler(event, self.ctx.plugin_manager.context, **params)
ready_to_call = handler.handler(event, self.ctx.plugin_manager.context, **params)
else:
logger.debug("calling star handler: %s" % handler.handler_full_name)
ret = await handler.handler(star_cls_obj, event, **params)
ready_to_call = handler.handler(star_cls_obj, event, **params)
logger.debug("star handler %s called" % handler.handler_full_name)
if ret:
assert isinstance(ret, (MessageEventResult, CommandResult)), "如果有返回值,必须是 MessageEventResult 或 CommandResult 类型。"
event.stop_event()
event.set_result(ret)
# 执行后续步骤来发送消息
yield
if isinstance(ready_to_call, AsyncGenerator):
async for mer in ready_to_call:
# 如果处理函数是生成器,返回值只能是 MessageEventResult 或者 None(无返回值)
if mer:
assert isinstance(mer, (MessageEventResult, CommandResult)), "如果有返回值,必须是 MessageEventResult 或 CommandResult 类型。"
event.set_result(mer)
yield
else:
if event.get_result():
yield
elif inspect.iscoroutine(ready_to_call):
# 如果只是一个 coroutine
ret = await ready_to_call
if ret:
# 如果有返回值
assert isinstance(ret, (MessageEventResult, CommandResult)), "如果有返回值,必须是 MessageEventResult 或 CommandResult 类型。"
event.stop_event()
event.set_result(ret)
# 执行后续步骤来发送消息
if event.is_stopped() and event.get_result():
# 插件主动停止事件传播,并且有结果
event.continue_event()
yield
event.stop_event()
yield
elif not event.is_stopped and not event.get_result():
continue
else:
yield
event.clear_result() # 清除上一个 handler 的结果
except Exception as e:
logger.error(f"Star {handler.handler_full_name} handle error: {e}")
logger.error(traceback.format_exc())
logger.error(f"Star {handler.handler_full_name} handle error: {e}")
ret = f":(\n\n在调用插件 {star_map.get(handler.handler_module_str).name} 的处理函数 {handler.handler_name} 时出现异常:{e}"
event.set_result(MessageEventResult().message(ret))
yield
event.stop_event()
+2
View File
@@ -79,6 +79,8 @@ class Provider(abc.ABC):
@abc.abstractmethod
async def get_human_readable_context(self, session_id: str, page: int, page_size: int):
'''获取人类可读的上下文
page 从 1 开始
Example:
@@ -68,7 +68,7 @@ class LLMTunerModelLoader(Provider):
responses = await self.model.achat(**conf)
logger.debug(f"返回上下文:{responses}")
self.db_helper.update_llm_history(session_id, json.dumps(self.session_memory[session_id]))
self.db_helper.update_llm_history(session_id, json.dumps(self.session_memory[session_id]), self.meta().type)
self.session_memory[session_id].append({"role": "user", "content": prompt})
self.session_memory[session_id].append({"role": "assistant", "content": responses[-1].response_text})
return responses[-1].response_text
@@ -92,11 +92,17 @@ class LLMTunerModelLoader(Provider):
if session_id not in self.session_memory:
raise Exception("会话 ID 不存在")
contexts = []
temp_contexts = []
for record in self.session_memory[session_id]:
if record['role'] == "user":
contexts.append(f"User: {record['content']}")
temp_contexts.append(f"User: {record['content']}")
elif record['role'] == "assistant":
contexts.append(f"Assistant: {record['content']}")
temp_contexts.append(f"Assistant: {record['content']}")
contexts.insert(0, temp_contexts)
temp_contexts = []
# 展平 contexts 列表
contexts = [item for sublist in contexts for item in sublist]
# 计算分页
paged_contexts = contexts[(page-1)*page_size:page*page_size]