From 126ae083cb5da863bb57cbba8313b86f63cc13cc Mon Sep 17 00:00:00 2001 From: Danil Date: Fri, 27 Feb 2026 00:30:57 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=B0=D0=B2=D1=82=D0=BE-=D0=BE=D1=82=D0=B2=D0=B5?= =?UTF-8?q?=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AI/talk_handler.py | 27 +++++++++++++++++++++++++++ config.py | 5 +++++ main.py | 29 +++++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/AI/talk_handler.py b/AI/talk_handler.py index f1ed53d..dc5bfa7 100644 --- a/AI/talk_handler.py +++ b/AI/talk_handler.py @@ -93,3 +93,30 @@ async def handle_talk(message: Message): # При любых ошибках не падаем, а отдаём понятный fallback. logger.exception("Talk generation failed") await message.reply("Бля, кент, чёт движок заглох. Попробуй позже.") + + +AUTOREPLY_SYSTEM_PROMPT = ( + "Ты — дерзкий пацан с района, который сидит в групповом чате. " + "Ты НЕ отвечаешь на вопрос — ты сам влез в разговор. " + "Прокомментируй сообщение коротко (1-2 предложения), дерзко, на фене. " + "Можешь пошутить, подколоть, согласиться или послать. " + "НЕ начинай с обращения. Не используй формальный язык." +) + + +async def generate_autoreply(text: str) -> str: + url = f"{LLAMA_API_URL.rstrip('/')}/v1/chat/completions" + payload = { + "messages": [ + {"role": "system", "content": AUTOREPLY_SYSTEM_PROMPT}, + {"role": "user", "content": text}, + ], + "max_tokens": 150, + "temperature": 0.9, + "top_p": 0.9, + } + async with aiohttp.ClientSession() as session: + async with session.post(url, json=payload, timeout=aiohttp.ClientTimeout(total=120)) as resp: + data = await resp.json() + return data["choices"][0]["message"]["content"].strip() + diff --git a/config.py b/config.py index ea3e81b..ae8f7b4 100644 --- a/config.py +++ b/config.py @@ -76,6 +76,11 @@ SCHEDULE = { # --- Остальное --- KEYWORDS = {'крип', 'радиохэд', 'creep', 'radiohead'} +# --- Авто-ответы ИИ --- +AUTOREPLY_CHANCE = 0.10 +AUTOREPLY_COOLDOWN = 120 +AUTOREPLY_TRIGGERS = {'бот', 'фраер', 'кент', 'братуха', 'пацаны', 'чё как', 'базар'} + def get_hint_text(templates_str: str) -> str: return ( "Команды:\n" diff --git a/main.py b/main.py index 729f9a6..fd67740 100644 --- a/main.py +++ b/main.py @@ -18,7 +18,7 @@ from aiogram.types import ( from aiogram.client.default import DefaultBotProperties # Локальные импорты -from AI.talk_handler import handle_talk +from AI.talk_handler import handle_talk, generate_autoreply from zparser import get_military_data import config @@ -562,16 +562,41 @@ async def handle_gen_mem(message: Message, bot: Bot): return await message.reply_photo(BufferedInputFile(output.getvalue(), filename="meme.jpg")) +_last_autoreply_ts = 0 + async def handle_keywords(message: Message): + global _last_autoreply_ts if not message.text or message.text.startswith('/'): return - if any(re.search(rf'\b{word}\b', message.text.lower()) for word in config.KEYWORDS): + text_lower = message.text.lower() + + if any(re.search(rf'\b{word}\b', text_lower) for word in config.KEYWORDS): audio_path = config.BASE_DIR / "maket" / "Radiohead - Creep.mp3" if audio_path.exists(): await message.answer_audio( audio=FSInputFile(audio_path), caption="I'm a creep, I'm a weirdo...", ) + return + + import time as _time + now = _time.time() + triggered = any(trigger in text_lower for trigger in config.AUTOREPLY_TRIGGERS) + + should_reply = triggered or ( + random.random() < config.AUTOREPLY_CHANCE + and (now - _last_autoreply_ts) > config.AUTOREPLY_COOLDOWN + ) + + if should_reply: + try: + await message.bot.send_chat_action(chat_id=message.chat.id, action="typing") + response = await generate_autoreply(message.text) + if response: + await message.reply(response, parse_mode=None) + _last_autoreply_ts = now + except Exception: + logger.exception("Autoreply failed") # --- Запуск ---