style(legal): purge internal labels, remove question echo, clean status messages
This commit is contained in:
parent
1abadd9081
commit
b9acc30bf4
2 changed files with 27 additions and 32 deletions
|
|
@ -73,7 +73,10 @@ async def send_split_message(message: Message, header: str, body: str):
|
||||||
|
|
||||||
for idx, chunk in enumerate(chunks, 1):
|
for idx, chunk in enumerate(chunks, 1):
|
||||||
if idx == 1:
|
if idx == 1:
|
||||||
part_header = f"{header}\n\n" if len(chunks) == 1 else f"{header} (Часть 1/{len(chunks)}):\n\n"
|
if header:
|
||||||
|
part_header = f"{header}\n\n" if len(chunks) == 1 else f"{header} (Часть 1/{len(chunks)}):\n\n"
|
||||||
|
else:
|
||||||
|
part_header = "" if len(chunks) == 1 else f"<i>(Часть 1/{len(chunks)}):</i>\n\n"
|
||||||
else:
|
else:
|
||||||
part_header = f"<i>(Продолжение {idx}/{len(chunks)}):</i>\n\n"
|
part_header = f"<i>(Продолжение {idx}/{len(chunks)}):</i>\n\n"
|
||||||
|
|
||||||
|
|
@ -84,8 +87,12 @@ async def send_split_message(message: Message, header: str, body: str):
|
||||||
await message.answer(part_text, parse_mode='HTML', reply_markup=reply_markup)
|
await message.answer(part_text, parse_mode='HTML', reply_markup=reply_markup)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.warning(f"HTML send failed ({e}), falling back to plain text")
|
log.warning(f"HTML send failed ({e}), falling back to plain text")
|
||||||
plain_header = header if idx == 1 else f"(Продолжение {idx}/{len(chunks)}):"
|
if header:
|
||||||
await message.answer(f"{plain_header}\n\n{chunk}", reply_markup=reply_markup)
|
plain_header = header if idx == 1 else f"(Продолжение {idx}/{len(chunks)}):"
|
||||||
|
await message.answer(f"{plain_header}\n\n{chunk}", reply_markup=reply_markup)
|
||||||
|
else:
|
||||||
|
plain_header = "" if idx == 1 else f"(Продолжение {idx}/{len(chunks)}):\n\n"
|
||||||
|
await message.answer(f"{plain_header}{chunk}", reply_markup=reply_markup)
|
||||||
|
|
||||||
def get_legal_nav_keyboard() -> InlineKeyboardMarkup:
|
def get_legal_nav_keyboard() -> InlineKeyboardMarkup:
|
||||||
"""Инлайн-кнопки навигации после ответа юриста."""
|
"""Инлайн-кнопки навигации после ответа юриста."""
|
||||||
|
|
@ -130,12 +137,11 @@ async def cmd_legal_advisor(message: Message, state: FSMContext, bot: Bot):
|
||||||
if len(parts) > 1 and parts[0].casefold() in ("/юрист", "/jurist", "/вопрос"):
|
if len(parts) > 1 and parts[0].casefold() in ("/юрист", "/jurist", "/вопрос"):
|
||||||
inline_question = parts[1].strip()
|
inline_question = parts[1].strip()
|
||||||
if len(inline_question) > 3:
|
if len(inline_question) > 3:
|
||||||
status_msg = await message.answer("⏳ <i>Изучаю документы, сметы и решения ОСС дома № 37 в блокноте NotebookLM...</i>", parse_mode='HTML')
|
status_msg = await message.answer("⏳ <i>Изучаю документы, сметы, отчеты и решения дома № 37...</i>", parse_mode='HTML')
|
||||||
result = await legal_engine.query(prompt=inline_question, role=role)
|
result = await legal_engine.query(prompt=inline_question, role=role)
|
||||||
await status_msg.delete()
|
await status_msg.delete()
|
||||||
if result.get("success"):
|
if result.get("success"):
|
||||||
header = "⚖️ <b>Юридический ответ по документам дома № 37:</b>"
|
await send_split_message(message, "", result["text"])
|
||||||
await send_split_message(message, header, result["text"])
|
|
||||||
await state.set_state(LegalQuestionState.waiting_for_question)
|
await state.set_state(LegalQuestionState.waiting_for_question)
|
||||||
else:
|
else:
|
||||||
await message.answer(f"{result.get('text')}", parse_mode='HTML')
|
await message.answer(f"{result.get('text')}", parse_mode='HTML')
|
||||||
|
|
@ -143,8 +149,8 @@ async def cmd_legal_advisor(message: Message, state: FSMContext, bot: Bot):
|
||||||
|
|
||||||
text = (
|
text = (
|
||||||
"⚖️ <b>Юридический помощник (Дом № 37)</b>\n\n"
|
"⚖️ <b>Юридический помощник (Дом № 37)</b>\n\n"
|
||||||
"Напишите ваш вопрос (текстом или отправьте голосовое сообщение).\n"
|
"Напишите ваш вопрос или отправьте голосовое сообщение.\n"
|
||||||
"<i>Ответ формируется строго по сметам, договорам, протоколам ОСС и нормам ЖК РФ в блокноте NotebookLM.</i>"
|
"<i>Ответ формируется по сметам, отчетам, договорам и решениям ОСС дома.</i>"
|
||||||
)
|
)
|
||||||
await message.answer(text, parse_mode='HTML')
|
await message.answer(text, parse_mode='HTML')
|
||||||
await state.set_state(LegalQuestionState.waiting_for_question)
|
await state.set_state(LegalQuestionState.waiting_for_question)
|
||||||
|
|
@ -162,8 +168,8 @@ async def cb_legal_advisor(callback: CallbackQuery, state: FSMContext):
|
||||||
|
|
||||||
text = (
|
text = (
|
||||||
"⚖️ <b>Юридический помощник (Дом № 37)</b>\n\n"
|
"⚖️ <b>Юридический помощник (Дом № 37)</b>\n\n"
|
||||||
"Напишите ваш вопрос (текстом или отправьте голосовое сообщение).\n"
|
"Напишите ваш вопрос или отправьте голосовое сообщение.\n"
|
||||||
"<i>Ответ формируется строго по сметам, договорам, протоколам ОСС и нормам ЖК РФ в блокноте NotebookLM.</i>"
|
"<i>Ответ формируется по сметам, отчетам, договорам и решениям ОСС дома.</i>"
|
||||||
)
|
)
|
||||||
await callback.message.answer(text, parse_mode='HTML')
|
await callback.message.answer(text, parse_mode='HTML')
|
||||||
await state.set_state(LegalQuestionState.waiting_for_question)
|
await state.set_state(LegalQuestionState.waiting_for_question)
|
||||||
|
|
@ -239,7 +245,7 @@ async def process_text_legal_question(message: Message, state: FSMContext, bot:
|
||||||
question = message.text
|
question = message.text
|
||||||
|
|
||||||
status_msg = await message.answer(
|
status_msg = await message.answer(
|
||||||
"⏳ <i>Изучаю документы, сметы и решения ОСС дома № 37 в блокноте NotebookLM...</i>",
|
"⏳ <i>Изучаю документы, сметы, отчеты и решения дома № 37...</i>",
|
||||||
parse_mode='HTML'
|
parse_mode='HTML'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -256,23 +262,22 @@ async def process_text_legal_question(message: Message, state: FSMContext, bot:
|
||||||
try:
|
try:
|
||||||
await bot.send_message(
|
await bot.send_message(
|
||||||
chat_id=user_id,
|
chat_id=user_id,
|
||||||
text=f"⚖️ <b>Юридический ответ по документам дома № 37:</b>\n\n{format_telegram_html(result['text'])}",
|
text=format_telegram_html(result['text']),
|
||||||
parse_mode='HTML',
|
parse_mode='HTML',
|
||||||
reply_markup=get_legal_nav_keyboard()
|
reply_markup=get_legal_nav_keyboard()
|
||||||
)
|
)
|
||||||
await message.reply(
|
await message.reply(
|
||||||
"💬 <b>Ответ сформирован и отправлен вам в личные сообщения с ботом</b>, чтобы не перегружать общий чат дома.",
|
"💬 <b>Ответ отправлен вам в личные сообщения</b>, чтобы не перегружать общий чат дома.",
|
||||||
parse_mode='HTML'
|
parse_mode='HTML'
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
await message.reply(
|
await message.reply(
|
||||||
"💬 Пожалуйста, откройте личные сообщения с ботом (@lkmthreeseven_bot) и нажмите /start, чтобы получить ответ конфиденциально.",
|
"💬 Пожалуйста, откройте диалог с ботом (@lkmthreeseven_bot) и нажмите /start, чтобы получить ответ.",
|
||||||
parse_mode='HTML'
|
parse_mode='HTML'
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# В личном диалоге отвечаем напрямую
|
# В личном диалоге отвечаем напрямую без лишних префиксов
|
||||||
header = "⚖️ <b>Юридический ответ по документам дома № 37:</b>"
|
await send_split_message(message, "", result["text"])
|
||||||
await send_split_message(message, header, result["text"])
|
|
||||||
|
|
||||||
# Оставляем состояние активным, чтобы жилец мог сразу задать следующий вопрос без клика
|
# Оставляем состояние активным, чтобы жилец мог сразу задать следующий вопрос без клика
|
||||||
await state.set_state(LegalQuestionState.waiting_for_question)
|
await state.set_state(LegalQuestionState.waiting_for_question)
|
||||||
|
|
@ -293,7 +298,7 @@ async def process_voice_legal_question(message: Message, state: FSMContext, bot:
|
||||||
return
|
return
|
||||||
|
|
||||||
status_msg = await message.answer(
|
status_msg = await message.answer(
|
||||||
"🎙 <i>Распознаю аудио и сверяю с документами дома № 37 в NotebookLM...</i>",
|
"🎙 <i>Распознаю аудио и сверяю с документами дома № 37...</i>",
|
||||||
parse_mode='HTML'
|
parse_mode='HTML'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -304,7 +309,7 @@ async def process_voice_legal_question(message: Message, state: FSMContext, bot:
|
||||||
voice_file_path = str(TEMP_VOICE_DIR / f"voice_{user_id}_{int(message.date.timestamp())}.ogg")
|
voice_file_path = str(TEMP_VOICE_DIR / f"voice_{user_id}_{int(message.date.timestamp())}.ogg")
|
||||||
await bot.download_file(file_info.file_path, destination=voice_file_path)
|
await bot.download_file(file_info.file_path, destination=voice_file_path)
|
||||||
|
|
||||||
# Передаем в legal_engine (Gemini транскрибирует аудио в текст, затем NotebookLM ищет по базе дома)
|
# Передаем в legal_engine (Gemini транскрибирует аудио в текст, затем поиск по базе дома)
|
||||||
result = await legal_engine.query(prompt="", role=role, audio_path=voice_file_path)
|
result = await legal_engine.query(prompt="", role=role, audio_path=voice_file_path)
|
||||||
|
|
||||||
await status_msg.delete()
|
await status_msg.delete()
|
||||||
|
|
@ -313,13 +318,8 @@ async def process_voice_legal_question(message: Message, state: FSMContext, bot:
|
||||||
await message.answer(f"{result.get('text')}", parse_mode='HTML')
|
await message.answer(f"{result.get('text')}", parse_mode='HTML')
|
||||||
return
|
return
|
||||||
|
|
||||||
transcribed = result.get("transcribed_question")
|
# Отправляем чистый ответ без дублирования вопроса и без лишних плашек
|
||||||
if transcribed:
|
await send_split_message(message, "", result["text"])
|
||||||
header = f"⚖️ <b>Юридический ответ по документам дома № 37:</b>\n<i>(Вопрос: «{format_telegram_html(transcribed)}»)</i>"
|
|
||||||
else:
|
|
||||||
header = "⚖️ <b>Юридический ответ по документам дома № 37:</b>"
|
|
||||||
|
|
||||||
await send_split_message(message, header, result["text"])
|
|
||||||
await state.set_state(LegalQuestionState.waiting_for_question)
|
await state.set_state(LegalQuestionState.waiting_for_question)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
|
|
@ -255,12 +255,7 @@ class AILegalEngine:
|
||||||
# Никакого fallback на обычный Gemini! Выдаем честное уведомление об обновлении базы
|
# Никакого fallback на обычный Gemini! Выдаем честное уведомление об обновлении базы
|
||||||
return {
|
return {
|
||||||
"success": False,
|
"success": False,
|
||||||
"text": (
|
"text": "❌ <b>База документов дома № 37 временно обновляет сессию.</b>",
|
||||||
"❌ <b>База документов дома № 37 временно обновляет сессию.</b>\n\n"
|
|
||||||
"Юридический помощник не выдает выдуманных общих ответов нейросетей, "
|
|
||||||
"а обращается строго к протоколам ОСС, сметам и договорам нашего дома в NotebookLM. "
|
|
||||||
"Пожалуйста, повторите вопрос через минуту."
|
|
||||||
),
|
|
||||||
"role": role,
|
"role": role,
|
||||||
"latency_sec": latency,
|
"latency_sec": latency,
|
||||||
"error_detail": err_msg
|
"error_detail": err_msg
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue