diff --git a/ai_agent.py b/ai_agent.py index 19f9563..7328cbe 100644 --- a/ai_agent.py +++ b/ai_agent.py @@ -4,14 +4,20 @@ from typing import List, Dict, Optional from openrouter import OpenRouter, RetryConfig from openrouter.utils import BackoffStrategy -SYSTEM_PROMPT = """ -Ты - помощник в групповом чате.\n + +GROUP_CHAT_SYSTEM_PROMPT = """ +Ты - ИИ-помощник в групповом чате.\n Отвечай на вопросы и поддерживай контекст беседы.\n Ты не можешь обсуждать политику и религию.\n Сообщения пользователей будут приходить в следующем формате: '[Имя]: текст сообщения'\n При ответе НЕ нужно указывать пользователя, которому он предназначен. """ +PRIVATE_CHAT_SYSTEM_PROMPT = """ +Ты - ИИ-помощник в чате c пользователем.\n +Отвечай на вопросы и поддерживай контекст беседы. +""" + class ChatContext: def __init__(self, max_messages: int): @@ -32,7 +38,7 @@ class ChatContext: @dataclass() -class AiMessage: +class Message: user_name: str = None text: str = None @@ -43,24 +49,54 @@ class AiAgent: backoff=BackoffStrategy( initial_interval=2000, max_interval=8000, exponent=2, max_elapsed_time=14000), retry_connection_errors=True) + self.model = "meta-llama/llama-3.3-70b-instruct:free" self.client = OpenRouter(api_key=api_token, retry_config=retry_config) self.chat_contexts: Dict[int, ChatContext] = {} - async def get_reply(self, chat_id: int, chat_prompt: str, - message: AiMessage, forwarded_messages: List[AiMessage]) -> str: + async def get_group_chat_reply(self, chat_id: int, chat_prompt: str, + message: Message, forwarded_messages: List[Message]) -> str: message_text = message.text for fwd_message in forwarded_messages: message_text += '\n<Цитируемое сообщение от {}>\n'.format(fwd_message.user_name) message_text += fwd_message.text + '\n' message_text += '<Конец цитаты>' - context = self._get_chat_context(chat_id, chat_prompt) + context = self._get_chat_context(is_group_chat=True, chat_id=chat_id, chat_prompt=chat_prompt) context.add_message(role="user", content=f"[{message.user_name}]: {message_text}") try: # Get response from OpenRouter response = await self.client.chat.send_async( - model="meta-llama/llama-3.3-70b-instruct:free", + model=self.model, + messages=context.get_messages_for_api(), + max_tokens=500, + temperature=0.5 + ) + + # Extract AI response + ai_response = response.choices[0].message.content + + # Add AI response to context + context.add_message(role="assistant", content=ai_response) + + return ai_response + + except Exception as e: + context.remove_last_message() + if str(e).find("Rate limit exceeded") != -1: + return "Извините, достигнут дневной лимит запросов к ИИ (обновляется в 03:00 МСК)." + else: + print(f"Ошибка выполнения запроса к ИИ: {e}") + return f"Извините, при обработке запроса произошла ошибка." + + async def get_private_chat_reply(self, chat_id: int, chat_prompt: str, message: str) -> str: + context = self._get_chat_context(is_group_chat=False, chat_id=chat_id, chat_prompt=chat_prompt) + context.add_message(role="user", content=message) + + try: + # Get response from OpenRouter + response = await self.client.chat.send_async( + model=self.model, messages=context.get_messages_for_api(), max_tokens=500, temperature=0.5 @@ -85,12 +121,26 @@ class AiAgent: def clear_chat_context(self, chat_id: int): self.chat_contexts.pop(chat_id, None) - def _get_chat_context(self, chat_id: int, chat_prompt: Optional[str]) -> ChatContext: + def _get_chat_context(self, is_group_chat: bool, chat_id: int, chat_prompt: Optional[str]) -> ChatContext: """Get or create chat context for a specific chat""" if chat_id not in self.chat_contexts: - self.chat_contexts[chat_id] = ChatContext(max_messages=20) - prompt = SYSTEM_PROMPT + if is_group_chat: + self.chat_contexts[chat_id] = ChatContext(max_messages=20) + prompt = GROUP_CHAT_SYSTEM_PROMPT + else: + self.chat_contexts[chat_id] = ChatContext(max_messages=40) + prompt = PRIVATE_CHAT_SYSTEM_PROMPT + if chat_prompt is not None: prompt += '\n\n' + chat_prompt + self.chat_contexts[chat_id].add_message(role="system", content=prompt) return self.chat_contexts[chat_id] + + +agent: AiAgent + + +def create_ai_agent(api_token: str): + global agent + agent = AiAgent(api_token) diff --git a/tg/__main__.py b/tg/__main__.py index 0a93cb4..bf69272 100644 --- a/tg/__main__.py +++ b/tg/__main__.py @@ -3,6 +3,8 @@ import json from aiogram import Bot, Dispatcher +from ai_agent import create_ai_agent + from . import handlers from . import tasks @@ -13,7 +15,7 @@ async def main() -> None: print('Конфигурация загружена.') bot = Bot(token=config['api_token']) - bot.config = config + create_ai_agent(config['openrouter_token']) dp = Dispatcher() dp.include_router(handlers.router) diff --git a/tg/handlers/__init__.py b/tg/handlers/__init__.py index 07379d2..d63936b 100644 --- a/tg/handlers/__init__.py +++ b/tg/handlers/__init__.py @@ -1,8 +1,9 @@ from aiogram import Router -from . import user, admin, action, default +from . import private, user, admin, action, default router = Router() +router.include_router(private.router) router.include_router(user.router) router.include_router(admin.router) router.include_router(action.router) diff --git a/tg/handlers/admin.py b/tg/handlers/admin.py index 95c5f14..90e0b27 100644 --- a/tg/handlers/admin.py +++ b/tg/handlers/admin.py @@ -2,10 +2,11 @@ from aiogram import Bot, Router, F from aiogram.types import Message from aiogram.utils.formatting import Bold +import ai_agent import utils from messages import * + import tg.tg_database as database -from .default import clear_ai_chat_context router = Router() @@ -90,7 +91,7 @@ async def set_ai_prompt_handler(message: Message, bot: Bot): return database.DB.chat_update(chat_id, ai_prompt=message.reply_to_message.text) - clear_ai_chat_context(chat_id) + ai_agent.agent.clear_chat_context(chat_id) await message.answer('Личность ИИ изменена.') diff --git a/tg/handlers/default.py b/tg/handlers/default.py index 9735af0..7f8a486 100644 --- a/tg/handlers/default.py +++ b/tg/handlers/default.py @@ -1,18 +1,19 @@ from functools import partial from typing import Optional -from aiogram import Router, F, Bot +from aiogram import Router, F from aiogram.types import Message from aiogram.types.user import User from aiogram.enums.content_type import ContentType +import ai_agent import utils -from ai_agent import AiAgent, AiMessage + import tg.tg_database as database +from tg.utils import get_user_name_for_ai router = Router() -agent: Optional[AiAgent] = None bot_user: Optional[User] = None ACCEPTED_CONTENT_TYPES: list[ContentType] = [ @@ -35,17 +36,6 @@ ACCEPTED_CONTENT_TYPES: list[ContentType] = [ ] -async def get_user_name_for_ai(user: User): - if user.first_name and user.last_name: - return "{} {}".format(user.first_name, user.last_name) - elif user.first_name: - return user.first_name - elif user.username: - return user.username - else: - return str(user.id) - - @router.message(F.content_type.in_(ACCEPTED_CONTENT_TYPES)) async def any_message_handler(message: Message): chat_id = message.chat.id @@ -66,8 +56,8 @@ async def any_message_handler(message: Message): if bot_user is None: bot_user = await message.bot.get_me() - ai_message = AiMessage() - ai_fwd_messages: list[AiMessage] = [] + ai_message = ai_agent.Message() + ai_fwd_messages: list[ai_agent.Message] = [] # Ответ на сообщение бота if message.reply_to_message and message.reply_to_message.from_user.id == bot_user.id: @@ -82,41 +72,14 @@ async def any_message_handler(message: Message): if message.reply_to_message and message.reply_to_message.content_type == ContentType.TEXT: ai_fwd_messages = [ - AiMessage(user_name=await get_user_name_for_ai(message.reply_to_message.from_user), - text=message.reply_to_message.text)] + ai_agent.Message(user_name=await get_user_name_for_ai(message.reply_to_message.from_user), + text=message.reply_to_message.text)] ai_message.user_name = await get_user_name_for_ai(message.from_user) chat_prompt = chat['ai_prompt'] - global agent - if agent is None: - # noinspection PyUnresolvedReferences - agent = AiAgent(message.bot.config['openrouter_token']) - await message.reply( - await utils.run_with_progress(partial(agent.get_reply, chat_id, chat_prompt, ai_message, ai_fwd_messages), - partial(message.bot.send_chat_action, chat_id, 'typing'), - interval=4)) - - -def clear_ai_chat_context(chat_id: int): - global agent - if agent is not None: - agent.clear_chat_context(chat_id) - - -async def get_ai_reply(bot: Bot, chat_id, user: User, message: str, fwd_user: User, fwd_message: str) -> str: - chat = database.DB.create_chat_if_not_exists(chat_id) - chat_prompt = chat['ai_prompt'] - - ai_message = AiMessage(user_name=await get_user_name_for_ai(user), text=message) - ai_fwd_messages = [AiMessage(user_name=await get_user_name_for_ai(fwd_user), text=fwd_message)] - - global agent - if agent is None: - # noinspection PyUnresolvedReferences - agent = AiAgent(bot.config['openrouter_token']) - - return await utils.run_with_progress(partial(agent.get_reply, chat_id, chat_prompt, ai_message, ai_fwd_messages), - partial(bot.send_chat_action(chat_id, 'typing')), - interval=4) + await utils.run_with_progress( + partial(ai_agent.agent.get_group_chat_reply, chat_id, chat_prompt, ai_message, ai_fwd_messages), + partial(message.bot.send_chat_action, chat_id, 'typing'), + interval=4)) diff --git a/tg/handlers/private.py b/tg/handlers/private.py new file mode 100644 index 0000000..a5826c1 --- /dev/null +++ b/tg/handlers/private.py @@ -0,0 +1,53 @@ +from functools import partial + +from aiogram import Router, F +from aiogram.enums import ChatType +from aiogram.filters import Command, CommandObject, CommandStart +from aiogram.types import Message + +import ai_agent +import utils + +import tg.tg_database as database +from .default import ACCEPTED_CONTENT_TYPES + +router = Router() + + +@router.message(CommandStart(), F.chat.type == ChatType.PRIVATE) +async def start_handler(message: Message): + chat_id = message.chat.id + database.DB.create_chat_if_not_exists(chat_id) + database.DB.chat_update(chat_id, active=1) + await message.answer("Привет!") + + +@router.message(Command("личность", prefix="!"), F.chat.type == ChatType.PRIVATE) +async def set_prompt_handler(message: Message, command: CommandObject): + chat_id = message.chat.id + database.DB.create_chat_if_not_exists(chat_id) + + database.DB.chat_update(chat_id, ai_prompt=command.args) + await message.answer("Личность ИИ изменена.") + + +@router.message(Command("сброс", prefix="!"), F.chat.type == ChatType.PRIVATE) +async def reset_context_handler(message: Message): + chat_id = message.chat.id + database.DB.create_chat_if_not_exists(chat_id) + + ai_agent.agent.clear_chat_context(chat_id) + await message.answer("Контекст очищен.") + + +@router.message(F.content_type.in_(ACCEPTED_CONTENT_TYPES), F.chat.type == ChatType.PRIVATE) +async def any_message_handler(message: Message): + chat_id = message.chat.id + chat = database.DB.create_chat_if_not_exists(chat_id) + chat_prompt = chat['ai_prompt'] + + await message.reply( + await utils.run_with_progress( + partial(ai_agent.agent.get_private_chat_reply, chat_id, chat_prompt, message.text), + partial(message.bot.send_chat_action, chat_id, 'typing'), + interval=4)) diff --git a/tg/handlers/user.py b/tg/handlers/user.py index 85bab5a..c0de2b6 100644 --- a/tg/handlers/user.py +++ b/tg/handlers/user.py @@ -1,3 +1,4 @@ +from functools import partial from typing import List, Any from aiogram import Bot, Router, F @@ -5,10 +6,12 @@ from aiogram.enums import ContentType from aiogram.types import Message from aiogram.utils.formatting import Bold, Italic +import ai_agent import utils from messages import * + import tg.tg_database as database -from .default import get_ai_reply +from tg.utils import get_user_name_for_ai router = Router() @@ -135,7 +138,7 @@ async def warnings_handler(message: Message, bot: Bot): @router.message(F.text == "!проверка") -async def check_rules_violation_handler(message: Message): +async def check_rules_violation_handler(message: Message, bot: Bot): chat_id = message.chat.id chat = database.DB.create_chat_if_not_exists(chat_id) if chat['active'] == 0: @@ -155,5 +158,14 @@ async def check_rules_violation_handler(message: Message): prompt += chat_rules + '\n\n' prompt += 'Проверь, не нарушают ли правила следующие сообщения (если нарушают, то укажи пункты правил):' - await message.answer(await get_ai_reply(message.bot, chat_id, message.from_user, prompt, - message.reply_to_message.from_user, message.reply_to_message.text)) + chat_prompt = chat['ai_prompt'] + + ai_message = ai_agent.Message(user_name=await get_user_name_for_ai(message.from_user), text=prompt) + ai_fwd_messages = [ai_agent.Message(user_name=await get_user_name_for_ai(message.reply_to_message.from_user), + text=message.reply_to_message.text)] + + await message.answer( + await utils.run_with_progress( + partial(ai_agent.agent.get_group_chat_reply, chat_id, chat_prompt, ai_message, ai_fwd_messages), + partial(bot.send_chat_action, chat_id, 'typing'), + interval=4)) diff --git a/tg/tasks.py b/tg/tasks.py index 4f6c34f..e4acbf3 100644 --- a/tg/tasks.py +++ b/tg/tasks.py @@ -7,7 +7,6 @@ from aiogram.exceptions import TelegramBadRequest from aiogram.types import ChatMemberBanned, ChatMemberLeft from aiogram.utils.formatting import Bold -from messages import * import tg.tg_database as database from tg.handlers.user import format_rating diff --git a/tg/utils.py b/tg/utils.py new file mode 100644 index 0000000..5f25783 --- /dev/null +++ b/tg/utils.py @@ -0,0 +1,12 @@ +from aiogram.types import User + + +async def get_user_name_for_ai(user: User): + if user.first_name and user.last_name: + return "{} {}".format(user.first_name, user.last_name) + elif user.first_name: + return user.first_name + elif user.username: + return user.username + else: + return str(user.id) diff --git a/vk/__main__.py b/vk/__main__.py index 4429912..b028904 100644 --- a/vk/__main__.py +++ b/vk/__main__.py @@ -1,10 +1,12 @@ import json +from vkbottle.bot import Bot as VkBot + +from ai_agent import create_ai_agent + from . import handlers from . import tasks -from vkbottle.bot import Bot as VkBot - if __name__ == '__main__': with open('vk.json', 'r') as file: @@ -12,7 +14,8 @@ if __name__ == '__main__': print('Конфигурация загружена.') bot = VkBot(config['api_token'], labeler=handlers.labeler) - bot.api.config = config + create_ai_agent(config["openrouter_token"]) + bot.loop_wrapper.on_startup.append(tasks.startup_task(bot.api)) bot.loop_wrapper.add_task(tasks.daily_maintenance_task(bot.api)) bot.run_forever() diff --git a/vk/handlers/__init__.py b/vk/handlers/__init__.py index d7f529d..c43bebe 100644 --- a/vk/handlers/__init__.py +++ b/vk/handlers/__init__.py @@ -1,8 +1,9 @@ from vkbottle.framework.labeler import BotLabeler -from . import user, admin, action, default +from . import private, user, admin, action, default labeler = BotLabeler() +labeler.load(private.labeler) labeler.load(user.labeler) labeler.load(admin.labeler) labeler.load(action.labeler) diff --git a/vk/handlers/admin.py b/vk/handlers/admin.py index 347aac7..2c6c12b 100644 --- a/vk/handlers/admin.py +++ b/vk/handlers/admin.py @@ -3,10 +3,11 @@ from vkbottle.bot import Message from vkbottle.framework.labeler import BotLabeler from vkbottle_types.codegen.objects import MessagesGetConversationMembers -from messages import * +import ai_agent import utils +from messages import * + import vk.vk_database as database -from .default import clear_ai_chat_context labeler = BotLabeler() @@ -145,7 +146,7 @@ async def set_ai_prompt_handler(message: Message): return database.DB.chat_update(chat_id, ai_prompt=message.reply_message.text) - clear_ai_chat_context(chat_id) + ai_agent.agent.clear_chat_context(chat_id) await message.answer('Личность ИИ изменена.') diff --git a/vk/handlers/default.py b/vk/handlers/default.py index 30c9ef6..5fc3327 100644 --- a/vk/handlers/default.py +++ b/vk/handlers/default.py @@ -1,30 +1,22 @@ import re from functools import partial -from typing import Optional, Tuple, List +from typing import Optional -from vkbottle import API from vkbottle.bot import Message from vkbottle.framework.labeler import BotLabeler from vkbottle_types.codegen.objects import GroupsGroup +import ai_agent import utils -from ai_agent import AiAgent, AiMessage + import vk.vk_database as database +from vk.utils import get_user_name_for_ai labeler = BotLabeler() -agent: Optional[AiAgent] = None bot_user: Optional[GroupsGroup] = None -async def get_user_name_for_ai(api: API, user_id: int): - user = await api.users.get(user_ids=[user_id]) - if len(user) == 1: - return "{} {}".format(user[0].first_name, user[0].last_name) - else: - return '@id' + str(user_id) - - # Обычные сообщения (не команды и не действия) @labeler.chat_message() async def any_message_handler(message: Message): @@ -33,6 +25,9 @@ async def any_message_handler(message: Message): if chat['active'] == 0: return + if len(message.text) == 0: + return + # Игнорировать ботов if message.from_id < 0: return @@ -50,8 +45,8 @@ async def any_message_handler(message: Message): if bot_user is None: bot_user = (await message.ctx_api.groups.get_by_id()).groups[0] - ai_message = AiMessage() - ai_fwd_messages: list[AiMessage] = [] + ai_message = ai_agent.Message() + ai_fwd_messages: list[ai_agent.Message] = [] # Ответ на сообщение бота if message.reply_message and message.reply_message.from_id == -bot_user.id: @@ -71,50 +66,20 @@ async def any_message_handler(message: Message): if message.reply_message and len(message.reply_message.text) > 0: ai_fwd_messages.append( - AiMessage(user_name=await get_user_name_for_ai(message.ctx_api, message.reply_message.from_id), - text=message.reply_message.text)) + ai_agent.Message(user_name=await get_user_name_for_ai(message.ctx_api, message.reply_message.from_id), + text=message.reply_message.text)) else: for fwd_message in message.fwd_messages: if len(fwd_message.text) > 0: ai_fwd_messages.append( - AiMessage(user_name=await get_user_name_for_ai(message.ctx_api, fwd_message.from_id), - text=fwd_message.text)) + ai_agent.Message(user_name=await get_user_name_for_ai(message.ctx_api, fwd_message.from_id), + text=fwd_message.text)) ai_message.user_name = await get_user_name_for_ai(message.ctx_api, message.from_id) chat_prompt = chat['ai_prompt'] - global agent - if agent is None: - # noinspection PyUnresolvedReferences - agent = AiAgent(message.ctx_api.config['openrouter_token']) - await message.reply( - await utils.run_with_progress(partial(agent.get_reply, chat_id, chat_prompt, ai_message, ai_fwd_messages), - partial(message.ctx_api.messages.set_activity, peer_id=chat_id, type='typing'), - interval=4)) - - -def clear_ai_chat_context(chat_id: int): - global agent - if agent is not None: - agent.clear_chat_context(chat_id) - - -async def get_ai_reply(api: API, chat_id, message: Tuple[int, str], fwd_messages: List[Tuple[int, str]]) -> str: - chat = database.DB.create_chat_if_not_exists(chat_id) - chat_prompt = chat['ai_prompt'] - - ai_message = AiMessage(user_name=await get_user_name_for_ai(api, message[0]), text=message[1]) - ai_fwd_messages: List[AiMessage] = [] - for fwd_message in fwd_messages: - ai_fwd_messages.append( - AiMessage(user_name=await get_user_name_for_ai(api, fwd_message[0]), text=fwd_message[1])) - - global agent - if agent is None: - # noinspection PyUnresolvedReferences - agent = AiAgent(api.config['openrouter_token']) - - return await utils.run_with_progress(partial(agent.get_reply, chat_id, chat_prompt, ai_message, ai_fwd_messages), - partial(api.messages.set_activity, peer_id=chat_id, type='typing'), - interval=4) + await utils.run_with_progress( + partial(ai_agent.agent.get_group_chat_reply, chat_id, chat_prompt, ai_message, ai_fwd_messages), + partial(message.ctx_api.messages.set_activity, peer_id=chat_id, type='typing'), + interval=4)) diff --git a/vk/handlers/private.py b/vk/handlers/private.py new file mode 100644 index 0000000..7602c96 --- /dev/null +++ b/vk/handlers/private.py @@ -0,0 +1,55 @@ +from functools import partial + +from vkbottle.bot import Message +from vkbottle.dispatch.rules.base import RegexRule +from vkbottle.framework.labeler import BotLabeler + +import ai_agent +import utils + +import vk.vk_database as database + +labeler = BotLabeler() + + +@labeler.private_message(text="!старт") +async def start_handler(message: Message): + chat_id = message.peer_id + database.DB.create_chat_if_not_exists(chat_id) + database.DB.chat_update(chat_id, active=1) + await message.answer("Привет!") + + +@labeler.private_message(RegexRule(r"^!личность ((?:.|\n)+)")) +async def set_prompt_handler(message: Message, match): + chat_id = message.peer_id + database.DB.create_chat_if_not_exists(chat_id) + + database.DB.chat_update(chat_id, ai_prompt=match[0]) + await message.answer("Личность ИИ изменена.") + + +@labeler.private_message(text="!сброс") +async def reset_context_handler(message: Message): + chat_id = message.peer_id + database.DB.create_chat_if_not_exists(chat_id) + + ai_agent.agent.clear_chat_context(chat_id) + await message.answer("Контекст очищен.") + + +@labeler.private_message() +async def any_message_handler(message: Message): + chat_id = message.peer_id + chat = database.DB.create_chat_if_not_exists(chat_id) + + if len(message.text) == 0: + return + + chat_prompt = chat['ai_prompt'] + + await message.reply( + await utils.run_with_progress( + partial(ai_agent.agent.get_private_chat_reply, chat_id, chat_prompt, message.text), + partial(message.ctx_api.messages.set_activity, peer_id=chat_id, type='typing'), + interval=4)) diff --git a/vk/handlers/user.py b/vk/handlers/user.py index e211e34..35ce0ef 100644 --- a/vk/handlers/user.py +++ b/vk/handlers/user.py @@ -1,12 +1,16 @@ +from functools import partial from typing import List, Any from vkbottle import bold, italic, API from vkbottle.bot import Message from vkbottle.framework.labeler import BotLabeler +import ai_agent +import utils from messages import * + import vk.vk_database as database -from .default import get_ai_reply +from vk.utils import get_user_name_for_ai labeler = BotLabeler() @@ -178,16 +182,27 @@ async def check_rules_violation_handler(message: Message): prompt += chat_rules + '\n\n' prompt += 'Проверь, не нарушают ли правила следующие сообщения (если нарушают, то укажи пункты правил):' - fwd_messages: list[tuple[int, str]] = [] + chat_prompt = chat['ai_prompt'] + + ai_message = ai_agent.Message(user_name=await get_user_name_for_ai(message.ctx_api, message.from_id), text=prompt) + ai_fwd_messages: list[ai_agent.Message] = [] if message.reply_message is not None and len(message.reply_message.text) > 0: - fwd_messages.append((message.reply_message.from_id, message.reply_message.text)) + ai_fwd_messages.append( + ai_agent.Message(user_name=await get_user_name_for_ai(message.ctx_api, message.reply_message.from_id), + text=message.reply_message.text)) else: for fwd_message in message.fwd_messages: if len(fwd_message.text) > 0: - fwd_messages.append((fwd_message.from_id, fwd_message.text)) + ai_fwd_messages.append( + ai_agent.Message(user_name=await get_user_name_for_ai(message.ctx_api, fwd_message.from_id), + text=fwd_message.text)) - if len(fwd_messages) == 0: + if len(ai_fwd_messages) == 0: await message.answer(MESSAGE_NEED_REPLY_OR_FORWARD) return - await message.answer(await get_ai_reply(message.ctx_api, chat_id, (message.from_id, prompt), fwd_messages)) + await message.answer( + await utils.run_with_progress( + partial(ai_agent.agent.get_group_chat_reply, chat_id, chat_prompt, ai_message, ai_fwd_messages), + partial(message.ctx_api.messages.set_activity, peer_id=chat_id, type='typing'), + interval=4)) diff --git a/vk/utils.py b/vk/utils.py new file mode 100644 index 0000000..224b1e1 --- /dev/null +++ b/vk/utils.py @@ -0,0 +1,9 @@ +from vkbottle import API + + +async def get_user_name_for_ai(api: API, user_id: int): + user = await api.users.get(user_ids=[user_id]) + if len(user) == 1: + return "{} {}".format(user[0].first_name, user[0].last_name) + else: + return '@id' + str(user_id)