Files
mai-bot/src/chat/event_helpers.py

170 lines
6.7 KiB
Python
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.
"""
事件消息构建工具
将 chat 层的消息对象 (SessionMessage / MessageSending) 转换为
核心事件系统使用的 MaiMessages供调用 event_bus.emit() 前使用。
"""
from typing import List, Optional, TYPE_CHECKING
from src.common.logger import get_logger
from src.core.types import EventType, MaiMessages
if TYPE_CHECKING:
from src.chat.message_receive.message import MessageSending, SessionMessage
from src.common.data_models.llm_data_model import LLMGenerationDataModel
logger = get_logger("event_helpers")
def build_event_message(
event_type: EventType | str,
message: Optional["SessionMessage | MessageSending | MaiMessages"] = None,
llm_prompt: Optional[str] = None,
llm_response: Optional["LLMGenerationDataModel"] = None,
stream_id: Optional[str] = None,
action_usage: Optional[List[str]] = None,
) -> Optional[MaiMessages]:
"""根据事件类型和输入,准备和转换消息对象。
迁移自 events_manager._prepare_message保持相同的行为。
"""
if isinstance(message, MaiMessages):
return message.deepcopy()
if message:
return _transform_event_message(message, llm_prompt, llm_response)
if event_type not in (EventType.ON_START, EventType.ON_STOP):
assert stream_id, "如果没有消息,必须为非启动/关闭事件提供流ID"
if event_type in (EventType.ON_MESSAGE, EventType.ON_PLAN, EventType.POST_LLM, EventType.AFTER_LLM):
return _build_message_from_stream(stream_id, llm_prompt, llm_response)
else:
return _build_message_without_raw(stream_id, llm_prompt, llm_response, action_usage)
return None # ON_START / ON_STOP 没有消息体
def _transform_event_message(
message: "SessionMessage | MessageSending",
llm_prompt: Optional[str] = None,
llm_response: Optional["LLMGenerationDataModel"] = None,
) -> MaiMessages:
"""将 SessionMessage / MessageSending 转换为 MaiMessages。"""
from maim_message import Seg
from src.chat.message_receive.message import MessageSending
transformed = MaiMessages(
llm_prompt=llm_prompt,
llm_response_content=llm_response.content if llm_response else None,
llm_response_reasoning=llm_response.reasoning if llm_response else None,
llm_response_model=llm_response.model if llm_response else None,
llm_response_tool_call=llm_response.tool_calls if llm_response else None,
raw_message=message.processed_plain_text or "",
additional_data={},
)
# 消息段处理
if isinstance(message, MessageSending):
if message.message_segment.type == "seglist":
transformed.message_segments = list(message.message_segment.data) # type: ignore
else:
transformed.message_segments = [message.message_segment]
else:
transformed.message_segments = [Seg(type="text", data=message.processed_plain_text or "")]
# stream_id
transformed.stream_id = message.session_id if hasattr(message, "session_id") else ""
# 处理后文本
transformed.plain_text = message.processed_plain_text
# 基本信息
if isinstance(message, MessageSending):
transformed.message_base_info["platform"] = message.platform
if message.session.group_id:
transformed.is_group_message = True
group_name = ""
if (
message.session.context
and message.session.context.message
and message.session.context.message.message_info.group_info
):
group_name = message.session.context.message.message_info.group_info.group_name
transformed.message_base_info.update(
{
"group_id": message.session.group_id,
"group_name": group_name,
}
)
transformed.message_base_info.update(
{
"user_id": message.bot_user_info.user_id,
"user_cardname": message.bot_user_info.user_cardname,
"user_nickname": message.bot_user_info.user_nickname,
}
)
if not transformed.is_group_message:
transformed.is_private_message = True
elif hasattr(message, "message_info") and message.message_info:
if message.platform:
transformed.message_base_info["platform"] = message.platform
if message.message_info.group_info:
transformed.is_group_message = True
transformed.message_base_info.update(
{
"group_id": message.message_info.group_info.group_id,
"group_name": message.message_info.group_info.group_name,
}
)
if message.message_info.user_info:
if not transformed.is_group_message:
transformed.is_private_message = True
transformed.message_base_info.update(
{
"user_id": message.message_info.user_info.user_id,
"user_cardname": message.message_info.user_info.user_cardname,
"user_nickname": message.message_info.user_info.user_nickname,
}
)
return transformed
def _build_message_from_stream(
stream_id: str,
llm_prompt: Optional[str] = None,
llm_response: Optional["LLMGenerationDataModel"] = None,
) -> MaiMessages:
"""从 stream_id 查找会话消息并转换。"""
from src.chat.message_receive.chat_manager import chat_manager
session = chat_manager.get_session_by_session_id(stream_id)
assert session, f"未找到流ID为 {stream_id} 的会话"
return _transform_event_message(session.context.message, llm_prompt, llm_response)
def _build_message_without_raw(
stream_id: str,
llm_prompt: Optional[str] = None,
llm_response: Optional["LLMGenerationDataModel"] = None,
action_usage: Optional[List[str]] = None,
) -> MaiMessages:
"""没有原始消息对象时,从 stream_id 构建最小 MaiMessages。"""
from src.chat.message_receive.chat_manager import chat_manager
session = chat_manager.get_session_by_session_id(stream_id)
assert session, f"未找到流ID为 {stream_id} 的会话"
return MaiMessages(
stream_id=stream_id,
llm_prompt=llm_prompt,
llm_response_content=llm_response.content if llm_response else None,
llm_response_reasoning=llm_response.reasoning if llm_response else None,
llm_response_model=llm_response.model if llm_response else None,
llm_response_tool_call=llm_response.tool_calls if llm_response else None,
is_group_message=session.is_group_session,
is_private_message=not session.is_group_session,
action_usage=action_usage,
additional_data={"response_is_processed": True},
)