feat: add dialogue compaction with summary integration

- Add /compact command for manual compaction
- Integrate summary loading from ChromaDB
- Add summary to AI prompt context
- Automatic compaction at 70% threshold
- Keep last 20 messages uncompressed

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
mirivlad 2026-02-25 12:22:31 +08:00
parent 417a858468
commit bff74741a6
1 changed files with 84 additions and 18 deletions

88
bot.py
View File

@ -213,8 +213,17 @@ async def handle_ai_task(update: Update, text: str):
def on_oauth_url(url: str):
pass # OAuth обрабатывается автоматически
# Формируем контекст с историей + памятью
history_context = "\n".join(state.ai_chat_history)
# Формируем контекст с историей + памятью + summary
# Получаем summary и последние сообщения из ChromaDB
summary = None
try:
summary, recent_messages = compactor.get_context_with_summary(limit=20)
# Формируем историю из последних сообщений
history_context = "\n".join([f"{msg['role']}: {msg['content']}" for msg in recent_messages])
except Exception as e:
logger.error(f"Ошибка загрузки summary: {e}")
# Fallback на старую логику
history_context = "\n".join(state.ai_chat_history)
# Получаем контекст из системы памяти (профиль + релевантные факты)
memory_context = get_context(user_id, query=text)
@ -231,15 +240,29 @@ async def handle_ai_task(update: Update, text: str):
# Собираем полный промпт с системным промптом
system_prompt = qwen_manager.load_system_prompt()
full_task = (
f"{system_prompt}\n\n"
f"=== КОНТЕКСТ ПАМЯТИ ===\n"
f"{memory_context}\n\n"
f"=== ИСТОРИЯ ДИАЛОГА ===\n"
f"{history_context}\n\n"
f"=== ЗАПРОС ПОЛЬЗОВАТЕЛЯ ===\n"
f"{text}"
)
# Формируем полный промпт с summary (если есть)
if summary:
full_task = (
f"{system_prompt}\n\n"
f"=== SUMMARY ДИАЛОГА (контекст) ===\n"
f"{summary}\n\n"
f"=== КОНТЕКСТ ПАМЯТИ ===\n"
f"{memory_context}\n\n"
f"=== ИСТОРИЯ ДИАЛОГА (последние 20 сообщений) ===\n"
f"{history_context}\n\n"
f"=== ЗАПРОС ПОЛЬЗОВАТЕЛЯ ===\n"
f"{text}"
)
else:
full_task = (
f"{system_prompt}\n\n"
f"=== КОНТЕКСТ ПАМЯТИ ===\n"
f"{memory_context}\n\n"
f"=== ИСТОРИЯ ДИАЛОГА ===\n"
f"{history_context}\n\n"
f"=== ЗАПРОС ПОЛЬЗОВАТЕЛЯ ===\n"
f"{text}"
)
# Выполняем задачу (системный промпт уже добавлен в full_task)
result = await qwen_manager.run_task(user_id, full_task, on_output, on_oauth_url, use_system_prompt=False)
@ -1371,6 +1394,48 @@ async def ai_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
)
@check_access
async def compact_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Обработка команды /compact — ручная компактификация истории диалога."""
user_id = update.effective_user.id
logger.info(f"Пользователь {user_id} запросил ручную компактификацию")
status_msg = await update.message.reply_text(
"🔄 **Запуск компактификации истории...**\n\n"
"_Сжатие старой истории в структурированный summary._\n"
"_Это может занять несколько секунд._",
parse_mode="Markdown"
)
result = await compactor.compact()
await status_msg.delete()
if result.success:
if result.messages_compressed > 0:
await update.message.reply_text(
f"✅ **Компактификация завершена!**\n\n"
f"📊 Сжато сообщений: `{result.messages_compressed}`\n"
f"📝 Длина summary: `{result.summary_length}` символов\n"
f"💾 Экономия токенов: ~`{result.tokens_saved}`\n\n"
f"_Summary автоматически используется в контексте диалога._",
parse_mode="Markdown"
)
else:
await update.message.reply_text(
" **Компактификация не требуется**\n\n"
"_Недостаточно сообщений для сжатия или summary уже актуален._",
parse_mode="Markdown"
)
else:
logger.error(f"Компактификация не удалась: {result.error}")
await update.message.reply_text(
f"⚠️ **Ошибка компактификации:**\n`{result.error}`",
parse_mode="Markdown"
)
@check_access
async def memory_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Обработка команды /memory — статистика памяти ИИ."""
@ -1567,6 +1632,7 @@ def main():
application.add_handler(CommandHandler("menu", menu_command))
application.add_handler(CommandHandler("stop", stop_command))
application.add_handler(CommandHandler("memory", memory_command))
application.add_handler(CommandHandler("compact", compact_command))
application.add_handler(CommandHandler("facts", facts_command))
application.add_handler(CommandHandler("forget", forget_command))
application.add_handler(CallbackQueryHandler(menu_callback))