From b582a579aaca3935db86d5993c805c1a660da6ab Mon Sep 17 00:00:00 2001 From: Admin Date: Tue, 13 Oct 2026 14:20:04 +0400 Subject: [PATCH] =?UTF-8?q?fix(legal):=20=D1=8F=D0=BF=D0=BE=D0=BD=D1=81?= =?UTF-8?q?=D0=BA=D0=B8=D0=B9=20=D0=BC=D0=B8=D0=BD=D0=B8=D0=BC=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D0=B7=D0=BC=20=D0=B2=20=D0=BE=D1=82=D0=B2=D0=B5=D1=82?= =?UTF-8?q?=D0=B0=D1=85=20=D1=8E=D1=80=D0=B8=D1=81=D1=82=D0=B0=20(=D1=83?= =?UTF-8?q?=D0=B1=D1=80=D0=B0=D0=BD=D1=8B=20=D1=81=D0=B0=D0=BC=D0=BE=D0=BD?= =?UTF-8?q?=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F,=20=D1=82=D0=B8?= =?UTF-8?q?=D1=82=D1=83=D0=BB=D1=8B,=20=D0=BF=D0=BB=D0=B0=D1=88=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B8=D1=81=D1=82=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=B8=20=D0=B7=D0=B0=D0=B4=D0=B5=D1=80=D0=B6=D0=B5?= =?UTF-8?q?=D0=BA)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- handlers/legal_advisor.py | 38 ++++++++++------------------- services/ai_legal_engine.py | 48 +++++++++++++------------------------ 2 files changed, 30 insertions(+), 56 deletions(-) diff --git a/handlers/legal_advisor.py b/handlers/legal_advisor.py index a4b52a1..ad7048c 100644 --- a/handlers/legal_advisor.py +++ b/handlers/legal_advisor.py @@ -124,22 +124,16 @@ async def cmd_legal_advisor(message: Message, state: FSMContext, bot: Bot): result = await legal_engine.query(prompt=inline_question, role=role) await status_msg.delete() if result.get("success"): - header = f"⚖️ Юридический ответ ({result.get('latency_sec')} сек):" + header = "⚖️ Юридический ответ:" await send_split_message(message, header, result["text"]) else: await message.answer(f"❌ Ошибка: {result.get('text')}", parse_mode='HTML') return - role_desc = { - "admin": "👑 Режим Стратегического Аналитика (Администратор)", - "lawyer": "⚖️ Режим Судебного Юриста (Совет дома / Активист)", - }.get(role, "🏡 Юридический Помощник") - text = ( - f"{role_desc}\n\n" - "Задайте ваш вопрос по ЖКХ, протечкам, тарифам, собраниям или спорам с управляющей компанией.\n\n" - "🎙 Вы можете написать текст или отправить голосовое сообщение!\n" - "Я проанализирую обращение по базе законов РФ и материалам дома." + "⚖️ Юридический помощник (ЖК РФ)\n\n" + "Напишите ваш вопрос (текстом или отправьте голосовое сообщение).\n" + "Ответ формируется по нормам законодательства РФ и судебной практике." ) await message.answer(text, parse_mode='HTML') await state.set_state(LegalQuestionState.waiting_for_question) @@ -157,16 +151,10 @@ async def cb_legal_advisor(callback: CallbackQuery, state: FSMContext): ) return - role_desc = { - "admin": "👑 Режим Стратегического Аналитика (Администратор)", - "lawyer": "⚖️ Режим Судебного Юриста (Совет дома / Активист)", - }.get(role, "🏡 Юридический Помощник") - text = ( - f"{role_desc}\n\n" - "Задайте ваш вопрос по ЖКХ, протечкам, тарифам, собраниям или спорам с управляющей компанией.\n\n" - "🎙 Вы можете написать текст или отправить голосовое сообщение!\n" - "Я проанализирую обращение по базе законов РФ и судебным материалам дома." + "⚖️ Юридический помощник (ЖК РФ)\n\n" + "Напишите ваш вопрос (текстом или отправьте голосовое сообщение).\n" + "Ответ формируется по нормам законодательства РФ и судебной практике." ) await callback.message.answer(text, parse_mode='HTML') await state.set_state(LegalQuestionState.waiting_for_question) @@ -189,7 +177,7 @@ async def process_text_legal_question(message: Message, state: FSMContext, bot: question = message.text status_msg = await message.answer( - "⏳ Анализирую нормативную базу и материалы дома (1–3 сек)...", + "⏳ Анализирую нормы законодательства РФ...", parse_mode='HTML' ) @@ -207,7 +195,7 @@ async def process_text_legal_question(message: Message, state: FSMContext, bot: try: await bot.send_message( chat_id=user_id, - text=f"⚖️ Ответ на ваш вопрос из чата дома:\n\n{format_telegram_html(result['text'])}", + text=f"⚖️ Юридический ответ:\n\n{format_telegram_html(result['text'])}", parse_mode='HTML' ) await message.reply( @@ -221,7 +209,7 @@ async def process_text_legal_question(message: Message, state: FSMContext, bot: ) else: # В личном диалоге отвечаем напрямую - header = f"⚖️ Юридический ответ ({result.get('latency_sec')} сек):" + header = "⚖️ Юридический ответ:" await send_split_message(message, header, result["text"]) await state.clear() @@ -243,7 +231,7 @@ async def process_voice_legal_question(message: Message, state: FSMContext, bot: return status_msg = await message.answer( - "🎙 Слушаю голосовое сообщение и сопоставляю с законами РФ...", + "🎙 Анализирую голосовое обращение по нормам законодательства...", parse_mode='HTML' ) @@ -260,10 +248,10 @@ async def process_voice_legal_question(message: Message, state: FSMContext, bot: await status_msg.delete() if not result.get("success"): - await message.answer(f"❌ Ошибка распознавания: {result.get('text')}", parse_mode='HTML') + await message.answer(f"❌ Ошибка: {result.get('text')}", parse_mode='HTML') return - header = f"🎙 Голосовой разбор ({result.get('latency_sec')} сек):" + header = "⚖️ Юридический ответ:" await send_split_message(message, header, result["text"]) except Exception as e: diff --git a/services/ai_legal_engine.py b/services/ai_legal_engine.py index 9ba2a60..de4e5df 100644 --- a/services/ai_legal_engine.py +++ b/services/ai_legal_engine.py @@ -41,35 +41,23 @@ class AILegalEngine: def get_role_instructions(self, role: str) -> str: if role == "resident": return ( - "РОЛЬ ДЛЯ ОТВЕТА: 'Соседский помощник для жильца'.\n" - "СТИЛЬ: Спокойный, уважительный, без сложного бюрократического языка и канцелярита.\n" + "СТИЛЬ ОТВЕТА: Спокойный, понятный, без бюрократического канцелярита.\n" "ТРЕБОВАНИЯ:\n" - "1. Объясни ситуацию простыми словами за 2-3 коротких абзаца.\n" - "2. Дай пошаговый житейский совет (Шаг 1, Шаг 2, Шаг 3).\n" - "3. Укажи, кто несет ответственность (УК, застройщик, водоканал, совет дома).\n" - "4. Если нужно подать заявление — приведи краткий текст (3-4 строки), который жилец может скопировать и отправить в УК." + "1. Суть ситуации простыми словами (1-2 абзаца).\n" + "2. Пошаговый порядок действий (Шаг 1, Шаг 2, Шаг 3).\n" + "3. Кто несет ответственность (УК, застройщик, поставщик ресурсов, совет дома).\n" + "4. Образец краткого заявления при необходимости." ) - elif role == "lawyer": + else: return ( - "РОЛЬ ДЛЯ ОТВЕТА: 'Профессиональный юрист по жилищному праву и защите прав потребителей'.\n" - "СТИЛЬ: Строгий, юридически выверенный, аргументированный.\n" + "СТИЛЬ ОТВЕТА: Сугубо юридический, строгий, аргументированный.\n" "ТРЕБОВАНИЯ:\n" - "1. Четкая правовая квалификация действий/бездействия лиц.\n" - "2. Прямые ссылки на статьи законов (ЖК РФ, ГК РФ, 59-ФЗ, ПП РФ № 354, ПП РФ № 491, Госстрой № 170, СанПиН 2.1.3684-21).\n" - "3. Оценка перспектив в суде или надзорных органах (ГЖИ, Прокуратура, Роспотребнадзор).\n" - "4. Готовый проект претензии / жалобы с правовой мотивировкой." + "1. Правовая квалификация ситуации со ссылками на статьи нормативных актов РФ (ЖК РФ, ГК РФ, 59-ФЗ, ЗоЗПП, ПП РФ № 354, ПП РФ № 491, Госстрой № 170, СанПиН).\n" + "2. Оценка рисков, перспектив в надзорных органах и суде.\n" + "3. Четкий алгоритм действий (досудебная претензия, жалоба в ГЖИ / прокуратуру, иск).\n" + "4. Готовый образец мотивировочной части претензии или заявления при необходимости." ) - elif role == "admin": - return ( - "РОЛЬ ДЛЯ ОТВЕТА: 'Главный аналитик Совета Дома и стратег судебных процессов'.\n" - "СТИЛЬ: Стратегический, системный, аналитический.\n" - "ТРЕБОВАНИЯ:\n" - "1. Полный расклад с точки зрения системной выгоды для всего дома.\n" - "2. Выявление уловок УК, скрытых манипуляций со сметами, протоколами ОСС или объемами коммунальных ресурсов.\n" - "3. Сравнение с прецедентами и судебной практикой Ульяновского областного суда и Верховного Суда РФ.\n" - "4. Стратегия принуждения госорганов к исполнению служебных обязанностей по 59-ФЗ и Приказу ГП № 45." - ) - return "Отвечай вежливо и по делу." + return "Отвечай строго по существу." async def _query_rest_api(self, prompt: str, system_instruction: str, model: str, audio_path: str = None) -> str: """Прямой асинхронный REST запрос к Google Gemini API.""" @@ -208,8 +196,11 @@ class AILegalEngine: } system_instruction = ( - "Ты — интеллектуальный юридический щит 10-подъездного многоквартирного дома по адресу: г. Ульяновск, пр-кт Ленинского Комсомола, д. 37 (МКД ЛенКом 37).\n" - "Дом ведет системную юридическую защиту прав собственников против нарушений управляющей компании, бездействия надзорных органов и фальсификаций.\n" + "Ты — профессиональный юридический консультант по жилищному праву РФ (ЖК РФ, ГК РФ, защита прав потребителей в сфере ЖКХ).\n" + "ЖЕСТКИЕ ПРАВИЛА ОФОРМЛЕНИЯ:\n" + "1. КАТЕГОРИЧЕСКИ ЗАПРЕЩЕНО писать любые самопрезентации, самоназвания, титулы, приветствия или регалии (никаких 'Я — аналитик', 'Главный стратег', 'Юридический щит', 'Здравствуйте', 'Я помогу вам').\n" + "2. Ответ начинать СТРОГО сразу по существу вопроса.\n" + "3. Полный минимализм: только факты, правовые нормы, статьи законов и пошаговый алгоритм действий. Без рекламной шелухи и упоминания технологий/моделей.\n" f"{self.get_role_instructions(role)}" ) @@ -224,11 +215,6 @@ class AILegalEngine: ) latency = (datetime.now() - start_time).total_seconds() - - # Если для админа не сработал блокнот, честно добавляем статус - if role == "admin" and not audio_path: - prefix = "📚 [Источник: База законов РФ / Резервный шлюз Gemini]\n(Сессия NotebookLM требует обновления куков)\n\n" - reply_text = prefix + reply_text return { "success": True,