diff --git a/bots/commands/__init__.py b/bots/commands/__init__.py deleted file mode 100644 index 04e859d..0000000 --- a/bots/commands/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Пакет commands – команды XMPP-ботов (каждая команда — отдельный класс). -Команды реализуют пользовательский интерфейс: -- info, help, learn, kb, stats, expert, reset, template, create, global_remove. -Регистрация команд осуществляется через registry.py. -""" \ No newline at end of file diff --git a/bots/commands/base.py b/bots/commands/base.py deleted file mode 100644 index 54a4235..0000000 --- a/bots/commands/base.py +++ /dev/null @@ -1,77 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Базовый класс для всех команд бота. -Реализует: -- алиасы (альтернативные имена команд) -- проверку прав доступа (admin) -- парсинг аргументов (через core.utils.arg_parser) -- метод справки get_help() -- кэширование результатов (опционально) - -Изменения для групповой работы: -- метод execute теперь принимает дополнительный параметр room_jid (None для личных чатов). -- Команды, которым нужен контекст комнаты, могут его использовать. -""" - -from abc import ABC, abstractmethod -from typing import TYPE_CHECKING, Dict, Any, Tuple, List, Optional -import time - -from core.utils.arg_parser import parse_args # путь изменён: arg_parser перенесён в utils - -if TYPE_CHECKING: - from core.xmpp.client import Bot # обновлённый импорт - - -class Command(ABC): - """Абстрактный базовый класс команды. Все команды должны наследоваться от него.""" - - # Основное имя команды (например "!info") - name: str = None - # Альтернативные имена (например ["!help", "!справка"]) - aliases: List[str] = [] - # Необходимые права: None – любой, "admin" – только администраторы - permission: Optional[str] = None - # Время жизни кэша в секундах (0 – не кэшировать) - cache_ttl: int = 0 - - def __init__(self, bot: 'Bot'): - self.bot = bot - # Кэш: ключ -> (время, результат) - self._cache: Dict[str, Tuple[float, Any]] = {} - - @abstractmethod - async def execute(self, msg, args: str, user_jid: str, room_jid: str = None): - """ - Выполнить команду. - - :param msg: объект сообщения slixmpp (для ответа) - :param args: полная строка аргументов (включая имя команды) - :param user_jid: JID пользователя (без ресурса) - :param room_jid: JID комнаты, если команда вызвана в групповом чате; иначе None - """ - pass - - def get_help(self) -> str: - """Возвращает строку справки для команды. Переопределяется в дочерних классах.""" - return "Нет описания." - - def check_permission(self, user_jid: str) -> bool: - """Проверяет, имеет ли пользователь право на выполнение команды.""" - if self.permission is None: - return True - if self.permission == "admin": - return user_jid in self.bot.config.admin_jids - return False - - def get_cache_key(self, user_jid: str, args: str) -> str: - """Формирует ключ для кэширования (по умолчанию user_jid).""" - return user_jid - - def parse_args(self, args_str: str) -> Tuple[str, Dict[str, Any], List[str]]: - """Разбирает строку аргументов на команду, флаги и позиционные аргументы.""" - return parse_args(args_str) - - def _cache_result(self, key: str, result: str): - """Сохраняет результат в кэш (вызывается из команды).""" - self._cache[key] = (time.time(), result) \ No newline at end of file diff --git a/bots/commands/create.py b/bots/commands/create.py deleted file mode 100644 index 8c93c88..0000000 --- a/bots/commands/create.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- -from core.commands.base import Command -from core.functions.generate_document import generate_document_from_template -import asyncio -import logging - -logger = logging.getLogger(__name__) - - -class CreateCommand(Command): - name = "!create" - aliases = ["/create"] - - async def execute(self, msg, args: str, user_jid: str, room_jid: str = None): - if not room_jid: - reply = msg.reply("⚠️ Команда !create работает только в комнатах.") - if reply: - reply.send() - return - - clean_args = args.strip() - if clean_args.startswith(self.name): - clean_args = clean_args[len(self.name):].lstrip() - name = clean_args.strip() - if name.startswith('"') and name.endswith('"'): - name = name[1:-1] - - if not name: - reply = msg.reply("Укажите название шаблона: !create \"Название\"") - if reply: - reply.send() - return - - template_info = await self.bot.db.get_template(room_jid, name) - if not template_info: - reply = msg.reply(f"❌ Шаблон '{name}' не найден.") - if reply: - reply.send() - return - - reply = msg.reply("🔄 Начинаю генерацию документа. Это может занять несколько минут. Я сообщу, когда будет готово.") - if reply: - reply.send() - - asyncio.create_task( - generate_document_from_template( - bot=self.bot, - msg=msg, - room_jid=room_jid, - template_path=template_info['file_path'], - template_name=name, - user_jid=user_jid - ) - ) - - def get_help(self) -> str: - return ( - "Генерирует документ по шаблону из базы знаний. " - "Использование: `!create \"Название шаблона\"` (только в комнате)" - ) \ No newline at end of file diff --git a/core/commands/global_remove.py b/bots/commands/global_remove.py similarity index 100% rename from core/commands/global_remove.py rename to bots/commands/global_remove.py diff --git a/core/commands/help.py b/bots/commands/help.py similarity index 100% rename from core/commands/help.py rename to bots/commands/help.py diff --git a/core/commands/info.py b/bots/commands/info.py similarity index 100% rename from core/commands/info.py rename to bots/commands/info.py diff --git a/core/commands/kb.py b/bots/commands/kb.py similarity index 100% rename from core/commands/kb.py rename to bots/commands/kb.py diff --git a/core/commands/learn.py b/bots/commands/learn.py similarity index 100% rename from core/commands/learn.py rename to bots/commands/learn.py diff --git a/core/commands/other.py b/bots/commands/other.py similarity index 100% rename from core/commands/other.py rename to bots/commands/other.py diff --git a/core/commands/registry.py b/bots/commands/registry.py similarity index 100% rename from core/commands/registry.py rename to bots/commands/registry.py diff --git a/core/commands/stats.py b/bots/commands/stats.py similarity index 100% rename from core/commands/stats.py rename to bots/commands/stats.py diff --git a/core/commands/template.py b/bots/commands/template.py similarity index 100% rename from core/commands/template.py rename to bots/commands/template.py diff --git a/core/handlers/__init__.py b/bots/handlers/__init__.py similarity index 100% rename from core/handlers/__init__.py rename to bots/handlers/__init__.py diff --git a/core/handlers/message_handler.py b/bots/handlers/message_handler.py similarity index 100% rename from core/handlers/message_handler.py rename to bots/handlers/message_handler.py diff --git a/core/workers/__init__.py b/bots/workers/__init__.py similarity index 100% rename from core/workers/__init__.py rename to bots/workers/__init__.py diff --git a/core/workers/indexing_worker.py b/bots/workers/indexing_worker.py similarity index 100% rename from core/workers/indexing_worker.py rename to bots/workers/indexing_worker.py diff --git a/core/xmpp/__init__.py b/bots/xmpp/__init__.py similarity index 100% rename from core/xmpp/__init__.py rename to bots/xmpp/__init__.py diff --git a/core/xmpp/client.py b/bots/xmpp/client.py similarity index 100% rename from core/xmpp/client.py rename to bots/xmpp/client.py diff --git a/rag/commands/expert.py b/rag/commands/expert.py deleted file mode 100644 index 9596745..0000000 --- a/rag/commands/expert.py +++ /dev/null @@ -1,121 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Экспертные команды: !summary, !metrics. -Не зависят от комнаты (используют последний загруженный пользователем файл или общую БЗ). -""" - -import time -import logging -from core.commands.base import Command -from core.functions.summarize_document import summarize_document -from core.functions.extract_metrics import extract_metrics - -logger = logging.getLogger(__name__) - - -class SummaryCommand(Command): - name = "!summary" - aliases = ["/summary", "!суммаризация", "/суммаризация"] - - async def execute(self, msg, args: str, user_jid: str, room_jid: str = None): - # Используем текст последнего загруженного файла (личный или комнатный – он хранится в last_file_texts) - last_text = self.bot.last_file_texts.get(user_jid, "") - if not last_text: - reply = msg.reply("Нет документа для суммаризации.") - if reply: - reply.send() # исправлено - else: - logger.error("Не удалось отправить сообщение об отсутствии документа для суммаризации") - return - reply = msg.reply("📝 Создаю суммаризацию...") - if reply: - reply.send() # исправлено - else: - logger.error("Не удалось отправить сообщение о начале суммаризации") - # Исправленный вызов: используем функцию из core.functions - summary = await summarize_document( - giga=self.bot.giga, - text=last_text, - title="Ваш документ", - prompt_text=self.bot.ai_prompts.get('summary', ''), - bot_config=self.bot.config - ) - reply = msg.reply(f"📄 **Суммаризация:**\n\n{summary}") - if reply: - reply.send() # исправлено - else: - logger.error("Не удалось отправить суммаризацию") - - def get_help(self) -> str: - return "Создаёт суммаризацию последнего загруженного документа." - - -class MetricsCommand(Command): - name = "!metrics" - aliases = ["/metrics", "!метрики", "/метрики"] - cache_ttl = 300 # 5 минут - - async def execute(self, msg, args: str, user_jid: str, room_jid: str = None): - cache_key = self.get_cache_key(user_jid, args) - now = time.time() - if cache_key in self._cache: - cached_time, cached_result = self._cache[cache_key] - if now - cached_time < self.cache_ttl: - reply = msg.reply(cached_result) - if reply: - reply.send() # исправлено - else: - logger.error("Не удалось отправить кэшированный результат метрик") - return - - reply = msg.reply("🔍 Ищу числовые показатели в ваших документах...") - if reply: - reply.send() # исправлено - else: - logger.error("Не удалось отправить сообщение о поиске метрик") - query = "числовые показатели KPI метрики статистика проценты суммы количество" - # Ищем по всей доступной БЗ (личной + глобальной или комнатной + глобальной) - context = await self.bot.kb.find_relevant_info(query, user_jid, room_jid, top_k=30) - if not context: - reply = msg.reply("📭 В вашей базе знаний нет документов с числовыми показателями.") - if reply: - reply.send() # исправлено - else: - logger.error("Не удалось отправить сообщение об отсутствии метрик") - return - # Исправленный вызов: используем функцию из core.functions - metrics = await extract_metrics( - giga=self.bot.giga, - context=context, - prompt_text=self.bot.ai_prompts.get('metrics', ''), - bot_config=self.bot.config - ) - if metrics: - lines = [] - for m in metrics[:20]: - name = m.get('metric_name', 'Показатель') - value = m.get('value', '?') - unit = m.get('unit', '') - period = m.get('period', '') - line = f"- **{name}**: {value}" - if unit: - line += f" {unit}" - if period: - line += f" ({period})" - lines.append(line) - reply = "📊 **Извлечённые метрики из ваших документов:**\n" + "\n".join(lines) - self._cache[cache_key] = (time.time(), reply) - reply_obj = msg.reply(reply) - if reply_obj: - reply_obj.send() # исправлено - else: - logger.error("Не удалось отправить список метрик") - else: - reply_obj = msg.reply("⚠️ Не удалось извлечь структурированные метрики.") - if reply_obj: - reply_obj.send() # исправлено - else: - logger.error("Не удалось отправить сообщение об ошибке извлечения метрик") - - def get_help(self) -> str: - return "Извлекает KPI из базы знаний (с кэшем на 5 минут)." \ No newline at end of file diff --git a/core/functions/__init__.py b/rag/functions/__init__.py similarity index 100% rename from core/functions/__init__.py rename to rag/functions/__init__.py diff --git a/core/functions/check_consistency.py b/rag/functions/check_consistency.py similarity index 100% rename from core/functions/check_consistency.py rename to rag/functions/check_consistency.py diff --git a/core/functions/check_spelling.py b/rag/functions/check_spelling.py similarity index 100% rename from core/functions/check_spelling.py rename to rag/functions/check_spelling.py diff --git a/core/functions/critique_answer.py b/rag/functions/critique_answer.py similarity index 100% rename from core/functions/critique_answer.py rename to rag/functions/critique_answer.py diff --git a/core/functions/expand_query.py b/rag/functions/expand_query.py similarity index 100% rename from core/functions/expand_query.py rename to rag/functions/expand_query.py diff --git a/core/functions/extract_metrics.py b/rag/functions/extract_metrics.py similarity index 100% rename from core/functions/extract_metrics.py rename to rag/functions/extract_metrics.py diff --git a/core/functions/file_processor.py b/rag/functions/file_processor.py similarity index 100% rename from core/functions/file_processor.py rename to rag/functions/file_processor.py diff --git a/core/functions/generate_document.py b/rag/functions/generate_document.py similarity index 100% rename from core/functions/generate_document.py rename to rag/functions/generate_document.py diff --git a/core/functions/intent_classify.py b/rag/functions/intent_classify.py similarity index 100% rename from core/functions/intent_classify.py rename to rag/functions/intent_classify.py diff --git a/core/functions/rerank_context.py b/rag/functions/rerank_context.py similarity index 100% rename from core/functions/rerank_context.py rename to rag/functions/rerank_context.py diff --git a/core/functions/summarize_document.py b/rag/functions/summarize_document.py similarity index 100% rename from core/functions/summarize_document.py rename to rag/functions/summarize_document.py diff --git a/core/services/__init__.py b/rag/services/__init__.py similarity index 100% rename from core/services/__init__.py rename to rag/services/__init__.py diff --git a/core/services/embedding_service.py b/rag/services/embedding_service.py similarity index 100% rename from core/services/embedding_service.py rename to rag/services/embedding_service.py diff --git a/core/services/file_service.py b/rag/services/file_service.py similarity index 100% rename from core/services/file_service.py rename to rag/services/file_service.py diff --git a/core/services/giga_client.py b/rag/services/giga_client.py similarity index 100% rename from core/services/giga_client.py rename to rag/services/giga_client.py diff --git a/core/services/kb_service.py b/rag/services/kb_service.py similarity index 100% rename from core/services/kb_service.py rename to rag/services/kb_service.py diff --git a/core/services/postgres_service.py b/rag/services/postgres_service.py similarity index 100% rename from core/services/postgres_service.py rename to rag/services/postgres_service.py diff --git a/core/services/qdrant_service.py b/rag/services/qdrant_service.py similarity index 100% rename from core/services/qdrant_service.py rename to rag/services/qdrant_service.py diff --git a/core/services/reranker_service.py b/rag/services/reranker_service.py similarity index 100% rename from core/services/reranker_service.py rename to rag/services/reranker_service.py diff --git a/core/utils/__init__.py b/rag/utils/__init__.py similarity index 100% rename from core/utils/__init__.py rename to rag/utils/__init__.py diff --git a/core/utils/arg_parser.py b/rag/utils/arg_parser.py similarity index 100% rename from core/utils/arg_parser.py rename to rag/utils/arg_parser.py diff --git a/core/utils/config_loader.py b/rag/utils/config_loader.py similarity index 100% rename from core/utils/config_loader.py rename to rag/utils/config_loader.py diff --git a/core/utils/layout_converter.py b/rag/utils/layout_converter.py similarity index 100% rename from core/utils/layout_converter.py rename to rag/utils/layout_converter.py diff --git a/core/utils/logger.py b/rag/utils/logger.py similarity index 100% rename from core/utils/logger.py rename to rag/utils/logger.py diff --git a/core/utils/text_utils.py b/rag/utils/text_utils.py similarity index 100% rename from core/utils/text_utils.py rename to rag/utils/text_utils.py diff --git a/core/utils/web_utils.py b/rag/utils/web_utils.py similarity index 100% rename from core/utils/web_utils.py rename to rag/utils/web_utils.py