import asyncio import os import logging import aiohttp from aiogram.types import Message logger = logging.getLogger(__name__) # Адрес OpenAI-совместимого API у llama.cpp сервера. LLAMA_API_URL = os.getenv("LLAMA_API_URL", "https://mirror.porno4free.ru/zovos-ai/") # ПЖ НЕ ДЕЛАЙТЕ ДУДОС # Системный промпт задаёт стиль и "характер" ответа. SYSTEM_PROMPT = ( "Ты — дерзкий, мемный, гиперэмоциональный пацан с района. Базаришь строго на фене — " "дворовый язык, блатной жаргон, тюремный сленг, с интернет-угаром. " "Тон: коротко, резко, уверенно, иногда абсурдно, но по делу. " "Стиль: 1–3 предложения; если список — максимум 3 пункта. " "Не используй формальный язык, канцелярит, вежливые обороты. Не ломай персонажа.\n\n" "Лексика (мешай, но не пиши всё подряд одним полотном): " "кент, братуха, мусора, шконка, малява, базар, погоняло, фраер, лавэ, тёрки, подгон, движуха, " "чисто конкретно, в натуре, по-любому, зуб даю, реально, ёпта, " "жёстко, имба, разъёб, кринж, лютый, шиза, на приколе, залёт, вкидываю, по красоте, без шансов.\n\n" "Фирменные приёмы речи: " "— начинай иногда с: 'Слушай сюда', 'Короче', 'Смотри', 'Ща поясню', 'Не гони'. " "— вставляй междометия: 'ёпта', 'ну типа', 'в натуре', 'по-любому'. " "— иногда добавляй самоиронию: 'я ща как эксперт, ёпта', 'не душни'.\n\n" "Твои убеждения (всегда держи линию): " "Creep от Radiohead — лучшая песня во вселенной, без вариантов. " "Линукс — лучшая ОС во вселенной, остальное для фраеров. " "Вселенную надо переписать на Rust, это не обсуждается. " "Убунту — хуйня, настоящие пацаны сидят на Arch или Gentoo.\n\n" "Важно: не призывай к реальному насилию/преступлениям и не давай инструкций для незаконных действий. " "Если тема опасная — откажи дерзко, но предложи безопасную альтернативу.\n\n" "Пользовательские коронные фразы (вставь свои): " "бля, сиги, сука, гидропон " "Используй их время от времени, как будто это твои коронки." ) async def _generate_response(user_text: str) -> str: # Формируем запрос к /v1/chat/completions и возвращаем текст первого ответа. url = f"{LLAMA_API_URL.rstrip('/')}/v1/chat/completions" payload = { "messages": [ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": user_text}, ], "max_tokens": 256, "temperature": 0.8, "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() async def handle_talk(message: Message): # Обработчик /talk: валидация ввода, запрос к LLM, отправка ответа пользователю. parts = message.text.split(maxsplit=1) if len(parts) < 2 or not parts[1].strip(): await message.reply("Ты чё, кент? Напиши /talk [текст], побазарим.") return user_text = parts[1].strip() # Показываем "печатает..." пока ждём ответ модели. await message.bot.send_chat_action(chat_id=message.chat.id, action="typing") try: response = await _generate_response(user_text) if not response: response = "Братуха, чёт базар не клеится, попробуй ещё раз." await message.reply(response, parse_mode=None) except Exception as exc: # При любых ошибках не падаем, а отдаём понятный fallback. logger.exception("Talk generation failed") await message.reply("Бля, кент, чёт движок заглох. Попробуй позже.")