From efa287ed35c5a12424f6f4d52285adcf6156c1ce Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Thu, 13 Mar 2025 17:40:28 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20=E6=94=AF=E6=8C=81=20LLM=20?= =?UTF-8?q?=E5=AF=B9=E5=BC=95=E7=94=A8=E6=B6=88=E6=81=AF=E7=9A=84=E6=84=9F?= =?UTF-8?q?=E7=9F=A5=20#783?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../platform/sources/telegram/tg_adapter.py | 48 +++++++++++++++---- packages/astrbot/main.py | 20 ++++++-- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/astrbot/core/platform/sources/telegram/tg_adapter.py b/astrbot/core/platform/sources/telegram/tg_adapter.py index b7d7a6e7e..3dde1802b 100644 --- a/astrbot/core/platform/sources/telegram/tg_adapter.py +++ b/astrbot/core/platform/sources/telegram/tg_adapter.py @@ -17,6 +17,7 @@ from astrbot.api.message_components import ( File as AstrBotFile, Video, At, + Reply, ) from astrbot.core.platform.astr_message_event import MessageSesion from astrbot.api.platform import register_platform_adapter @@ -68,7 +69,7 @@ class TelegramPlatformAdapter(Platform): ) message_handler = TelegramMessageHandler( filters=filters.ALL, # receive all messages - callback=self.convert_message, + callback=self.message_handler, ) self.application.add_handler(message_handler) self.client = self.application.bot @@ -104,33 +105,64 @@ class TelegramPlatformAdapter(Platform): chat_id=update.effective_chat.id, text=self.config["start_message"] ) + async def message_handler(self, update: Update, context: ContextTypes.DEFAULT_TYPE): + logger.debug(f"Telegram message: {update.message}") + abm = await self.convert_message(update, context) + await self.handle_msg(abm) + async def convert_message( - self, update: Update, context: ContextTypes.DEFAULT_TYPE + self, update: Update, context: ContextTypes.DEFAULT_TYPE, get_reply=True ) -> AstrBotMessage: + """转换 Telegram 的消息对象为 AstrBotMessage 对象。 + + @param update: Telegram 的 Update 对象。 + @param context: Telegram 的 Context 对象。 + @param get_reply: 是否获取回复消息。这个参数是为了防止多个回复嵌套。 + """ message = AstrBotMessage() # 获得是群聊还是私聊 - if update.effective_chat.type == ChatType.PRIVATE: + if update.message.chat.type == ChatType.PRIVATE: message.type = MessageType.FRIEND_MESSAGE else: message.type = MessageType.GROUP_MESSAGE - message.group_id = str(update.effective_chat.id) + message.group_id = str(update.message.chat.id) if update.message.message_thread_id: # Topic Group message.group_id += "#" + str(update.message.message_thread_id) message.message_id = str(update.message.message_id) - message.session_id = str(update.effective_chat.id) + message.session_id = str(update.message.chat.id) message.sender = MessageMember( - str(update.effective_user.id), update.effective_user.username + str(update.message.from_user.id), update.message.from_user.username ) message.self_id = str(context.bot.username) message.raw_message = update message.message_str = "" message.message = [] - logger.debug(f"Telegram message: {update.message}") + if update.message.reply_to_message: + # 获取回复消息 + reply_update = Update( + update_id=1, + message=update.message.reply_to_message, + ) + reply_abm = await self.convert_message(reply_update, context, False) + + message.message.append( + Reply( + id=reply_abm.message_id, + chain=reply_abm.message, + sender_id=reply_abm.sender.user_id, + sender_nickname=reply_abm.sender.nickname, + time=reply_abm.timestamp, + message_str=reply_abm.message_str, + text=reply_abm.message_str, + qq=reply_abm.sender.user_id, + ) + ) if update.message.text: + # 处理文本消息 plain_text = update.message.text if update.message.entities: @@ -178,7 +210,7 @@ class TelegramPlatformAdapter(Platform): Video(file=file.file_path, path=file.file_path), ] - await self.handle_msg(message) + return message async def handle_msg(self, message: AstrBotMessage): message_event = TelegramPlatformEvent( diff --git a/packages/astrbot/main.py b/packages/astrbot/main.py index c8ed2564d..463f24950 100644 --- a/packages/astrbot/main.py +++ b/packages/astrbot/main.py @@ -17,7 +17,7 @@ from astrbot.core.star.filter.permission import PermissionTypeFilter from astrbot.core.config.default import VERSION from .long_term_memory import LongTermMemory from astrbot.core import logger -from astrbot.api.message_components import Plain, Image +from astrbot.api.message_components import Plain, Image, Reply from typing import Union @@ -1088,12 +1088,17 @@ UID: {user_id} 此 ID 可用于设置管理员。 @filter.on_llm_request() async def decorate_llm_req(self, event: AstrMessageEvent, req: ProviderRequest): - """在请求 LLM 前注入人格信息、Identifier、时间等 System Prompt""" - logger.debug(req.conversation) - + """在请求 LLM 前注入人格信息、Identifier、时间、回复内容等 System Prompt""" if self.prompt_prefix: req.prompt = self.prompt_prefix + req.prompt + # 解析引用内容 + quote = None + for comp in event.message_obj.message: + if isinstance(comp, Reply): + quote = comp + break + if self.identifier: user_id = event.message_obj.sender.user_id user_nickname = event.message_obj.sender.nickname @@ -1129,6 +1134,13 @@ UID: {user_id} 此 ID 可用于设置管理员。 if begin_dialogs := persona["_begin_dialogs_processed"]: req.contexts[:0] = begin_dialogs + if quote and quote.message_str: + if quote.sender_nickname: + sender_info = f"(Sent by {quote.sender_nickname})" + else: + sender_info = "" + req.system_prompt += f"\nUser is quoting the message{sender_info}: {quote.message_str}, please consider the context." + if self.ltm: try: await self.ltm.on_req_llm(event, req)