# /opt/trueconf_bot/config/config.py import os import sys # Автоматическое определение корневой директории проекта (на уровень выше папки config) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # ========================================================= # ФУНКЦИЯ ЧТЕНИЯ .env # ========================================================= # Загружает переменные окружения из локального файла .env (если он существует) ENV_PATH = os.path.join(os.path.dirname(__file__), ".env") def load_env(filepath): try: with open(filepath, "r", encoding="utf-8") as f: for line in f: line = line.strip() if line and not line.startswith("#"): if "=" in line: key, value = line.split("=", 1) os.environ[key.strip()] = value.strip(' "\'\r\n') except FileNotFoundError: print(f"⚠️ Файл {filepath} не найден. Используются системные переменные.") load_env(ENV_PATH) # Карта соответствия: Имя переменной в боте -> Название карточки в сейфе (из локального .env) # ИСПРАВЛЕНО: Перенесено выше для корректной передачи списка в модуль ретраев CREDENTIALS_MAP = { "TC_PASSWORD": os.getenv("PW_ID_TC", "").strip(' "\'\r\n'), # Получит "bot_tcs" "SD_TOKEN": os.getenv("PW_ID_SD", "").strip(' "\'\r\n'), # Получит "sdesktoken" "AD_PASSWORD": os.getenv("PW_ID_AD", "").strip(' "\'\r\n'), # Получит "AD" "DB_PASSWORD": os.getenv("PW_ID_SQL", "").strip(' "\'\r\n'), # Получит "boss_base" } # ========================================================= # ИНТЕГРАЦИЯ С PASSWORK (Динамическая загрузка паролей) # ========================================================= PASSWORK_DIR = "/opt/passwork" if PASSWORK_DIR not in sys.path: sys.path.insert(0, PASSWORK_DIR) try: from passwork import get_passwork_secrets print("🔐 Обращение к модулю Passwork и выгрузка сейфа...") # ИСПРАВЛЕНО: Пробрасываем список целевых карточек для потокобезопасного ожидания сессии required_to_wait = [name for name in CREDENTIALS_MAP.values() if name] passwork_pool = get_passwork_secrets(required_cards=required_to_wait) except Exception as e: print(f"❌ КРИТИЧЕСКАЯ ОШИБКА: Не удалось подключить модуль Passwork: {e}") sys.exit(1) print("🔐 Распределение секретов и логинов по модулям бота...") for var_name, card_name in CREDENTIALS_MAP.items(): if not card_name: print(f"⚠️ Внимание: Название карточки для {var_name} не найдено в .env") continue clean_card_name = card_name.strip(' "\'\r\n') card_data = passwork_pool.get(clean_card_name) if card_data is None: print(f"❌ КРИТИЧЕСКАЯ ОШИБКА: Карточка с именем '{clean_card_name}' не найдена в сейфе Passwork!") sys.exit(1) # Динамически заполняем пароль/токен в глобальную область видимости config.py globals()[var_name] = card_data["password"].strip(' "\'\r\n') # ИСПРАВЛЕНО: Переведено на жесткое globals() назначение для исключения NameError во внешних модулях if var_name == "TC_PASSWORD": globals()["TC_LOGIN"] = card_data.get("login", "").strip(' "\'\r\n') elif var_name == "AD_PASSWORD": globals()["AD_USER"] = card_data.get("login", "").strip(' "\'\r\n') elif var_name == "DB_PASSWORD": globals()["DB_USER"] = card_data.get("login", "").strip(' "\'\r\n') print(f" ✓ {var_name} и логин успешно загружены из карточки '{clean_card_name}'") # ========================================================= # 1. ГЛОБАЛЬНЫЕ ФЛАГИ МОДУЛЕЙ # ========================================================= ENABLE_SERVICE_DESK = True # Модуль создания заявок в техподдержку ENABLE_PHOTO_BOT = True # Модуль обработки фото/сканов ENABLE_TRANSCRIPTION = True # Модуль расшифровки голосовых сообщений (Whisper) ENABLE_SEARCH_BOT = True # Модуль интеллектуального поиска по регламентам (RAG) ENABLE_INSTRUCT = True # Модуль инструкций (Trueconf, Почта) ENABLE_LK = True # Личный кабинет сотрудника (отпуска, расчетные листки, справки) # ========================================================= # 1.1 ТЕСТОВЫЙ МОД ФОТО-БОТА # Фото уходит НАПРЯМУЮ в ИИ (llama.cpp, тот же endpoint и промпт, # что в SibCemProfile/PhotoApp/photo_validator.py), результат # показывается пользователю. Само фото никуда НЕ ДОСЫЛАЕТСЯ # не применяется (ни в AD, ни в API, ни на модерацию). # ========================================================= PHOTO_TEST_MODE = False # Тестовый мод: фото напрямую в ИИ, результат показывается, фото никуда не публикуется PHOTO_TEST_AI_URL = os.getenv("PHOTO_TEST_AI_URL", "http://srvkem-ii-03:8083/v1/chat/completions") PHOTO_TEST_AI_MODEL = os.getenv( "PHOTO_TEST_AI_MODEL", "/opt/llama.cpp-cpu/build/bin/models/gemma-4-E4B-mtp/gemma-4-E4B-it-UD-Q4_K_XL.gguf" ) PHOTO_TEST_AI_TIMEOUT = float(os.getenv("PHOTO_TEST_AI_TIMEOUT", "180")) # ========================================================= # 2. КОНТРОЛЬ ДОСТУПА # ========================================================= ENABLE_WHITELIST = True # Включить режим закрытого бета-тестирования ALLOWED_USERS = [ # Список TrueConf ID разрешенных пользователей "ds.krivochenko@tcs.sibcem.ru", "mm.norenberg@tcs.sibcem.ru", "a.kirpichev@tcs.sibcem.ru", "bot_test@tcs.sibcem.ru", "v.s.sholohov@tcs.sibcem.ru" ] # ========================================================= # 3. НАСТРОЙКИ СВЯЗИ С КОРПОРАТИВНЫМИ СИСТЕМАМИ # ========================================================= TC_SERVER = os.getenv("TC_SERVER", "") # Адрес сервера TrueConf AD_SERVER = "ldap://172.16.20.20" # Адрес контроллера домена Active Directory AD_BASES = ( # Базовые пути поиска пользователей в AD (несколько OU) "OU=-Пользователи,DC=sibcem,DC=ru", "OU=Планшеты,OU=enabled,OU=БезКомпьютеров,DC=sibcem,DC=ru", ) SQL_SERVER = "SRVKEM-MOBILEIN.sibcem.ru" # Сервер MS SQL для работы Личного кабинета SQL_DB_NAME = "BossCopy" # База данных с информацией по кадрам и ЗП SD_URL = "https://servicedesk.sibcem.ru:8080" # URL портала ManageEngine ServiceDesk Plus DEFAULT_REQUESTER = "ai@sibcem.ru" # E-mail по умолчанию для заявок SMTP_SERVER = "srvkem-mail.sibcem.ru" # Corporate почтовый сервер SMTP_PORT = 25 # Порт SMTP DEFAULT_EMAIL_FROM = "ai@sibcem.ru" # Адрес отправителя системных писем бота EMAIL_COOLDOWN_SEC = 10.0 # Кулдаун отправки критических алертов администратору # Списки рассылок для системных уведомлений (берутся из .env, разделяются запятыми) ALERTS_SUPPORT_EMAILS = [e.strip() for e in os.getenv("ALERTS_SUPPORT_EMAILS", "ds.krivochenko@sibcem.ru").split(",") if e.strip()] ALERTS_DISABLED_USERS = [e.strip() for e in os.getenv("ALERTS_DISABLED_USERS", "").split(",") if e.strip()] ALERTS_ALL_TICKETS = [e.strip() for e in os.getenv("ALERTS_ALL_TICKETS", "").split(",") if e.strip()] # ========================================================= # 4. ВНЕШНИЕ МИКРОСЕРВИСЫ И ТАЙМАУТЫ СЕТИ # ========================================================= TRASH_API_URL = os.getenv("TRASH_API_URL", "http://127.0.0.1:8000/upload") TRANSCRIPTION_API_URL = "http://172.16.80.250:8000/" API_HTTP_TIMEOUT = 30.0 # ========================================================= # 5. ИИ: ЯЗЫКОВАЯ МОДЕЛЬ (Генерация текста) # ========================================================= # ИСПРАВЛЕНО: Добавлен суффикс .gguf для однозначной адресации модели в llama-server OLLAMA_URL = "http://172.16.80.47:8080/v1/chat/completions" OLLAMA_MODEL = "gemma-4-E4B-it-Q4_K_M.gguf" AI_HTTP_TIMEOUT = 180.0 OLLAMA_TEMPERATURE = 0.0 OLLAMA_NUM_CTX = 8192 OLLAMA_NUM_PREDICT = 1500 # --- Настройки для генерации темы (Lightweight model) --- OLLAMA_SUBJECT_URL = "http://172.16.80.47:8080/v1/chat/completions" OLLAMA_SUBJECT_MODEL = "gemma-4-E4B-it-Q4_K_M" # ========================================================= # 6. ИИ: RAG И ВЕКТОРНЫЙ ПОИСК (Работа с документами) # ========================================================= QDRANT_HOST = "localhost" QDRANT_PORT = 6333 QDRANT_COLLECTION = "sibcem_enterprise_docs" # --- НАСТРОЙКИ ВНЕШНЕГО EMBEDDING API (Векторизация) --- EMBEDDING_API_URL = "http://127.0.0.1:8010/embed" EMBEDDING_MODEL_NAME = "bge-m3" EMBEDDING_API_TOKEN = os.getenv("EMBEDDING_API_TOKEN", "").strip(' "\'\r\n') # Пути к ресурсам, формируемые динамически от корня папки бота SEARCH_DOCS_PATH = os.path.join(BASE_DIR, "enterprise_docs") LOGS_PATH = os.path.join(BASE_DIR, "search_bot", "logs") # --- НАСТРОЙКИ РЕРАНКЕРА (Кросс-энкодер для переоценки релевантности) --- ENABLE_RERANKER = True RERANKER_MODE = "REMOTE_LLAMACPP" # Настройки для режима "REMOTE_LLAMACPP" # ИСПРАВЛЕНО: Добавлен суффикс .gguf для точного роутинга на бэкенде llama-server (порт 8081) RERANKER_API_URL = "http://172.16.80.47:8081/v1/rerank" RERANKER_MODEL_NAME = "bge-reranker-v2-m3-Q8_0.gguf" # Настройки для режима "LOCAL" (в оперативной памяти) RERANK_MODEL_PATH = "/opt/models/bge-reranker" # --- НАСТРОЙКИ ФИЛЬТРАЦИИ И ЛИМИТОВ (Поиск) --- QDRANT_LIMIT = 10 RERANK_TOP_K = 10 MAX_AI_CONTEXTS = 6 MAX_CONTEXT_LENGTH = 15000 MAX_SINGLE_CHUNK_LENGTH = 1500 QDRANT_SCORE_THRESHOLD = 0.45 RERANK_SCORE_THRESHOLD = -3.5 TABLE_SCORE_THRESHOLD = 0.35 QDRANT_CHUNK_WINDOW = 2 QDRANT_SCROLL_LIMIT = 50 # ========================================================= # 7. НАСТРОЙКИ СПРАВОК И ТЕСТИРОВАНИЯ (Личный кабинет) # ========================================================= DOCUMENTS_TEST_MODE = False DOCUMENTS_TARGET_EMAIL = "ds.krivochenko@sibcem.ru" # ========================================================= # 8. ОТЛАДКА И АНАЛИТИКА # ========================================================= ENABLE_DEEP_PROFILING = True ENABLE_QDRANT_DEBUG = True LOG_RAW_CHUNKS = True DEBUG_TEXT_LIMIT = 250 # ========================================================= # 9. ПОДСИСТЕМА МОНИТОРИНГА И СТАТУСА БОТА (HEARTBEAT) # ========================================================= ADMIN_CHAT_ID = "744bad93e58c4c498e15468562c6a2da3b610e9c" ENABLE_HEARTBEAT_MONITOR = True HEARTBEAT_CHECK_INTERVAL_SEC = 10.0 HEARTBEAT_MAX_FAILURES = 3 # ========================================================= # 10. БЕЗОПАСНОСТЬ И ДВУХФАКТОРНАЯ АВТОРИЗАЦИЯ (2FA / OTP) # ========================================================= # Срок действия одноразового OTP-кода (180 секунд = 3 минуты) OTP_TTL_SEC = 180 # Максимальное количество попыток ввода OTP-кода до срабатывания защиты OTP_MAX_ATTEMPTS = 3 # Время полной аппаратной блокировки меню расчетных листов (1800 секунд = 30 минут) OTP_BLOCK_DURATION_SEC = 1800 # Глобальный таймаут неактивности пользователя в любом подменю (1800 секунд = 30 минут) SESSION_TIMEOUT = 1800 # ========================================================= # 11. МОДУЛЬ INSTRUCT: НАСТРОЙКИ SERVICE DESK: ГРУППА И ИСПОЛНИТЕЛЬ # ========================================================= SD_INSTRUCT_GROUP_NAME = "Техподдержка ХК" # Название группы в ServiceDesk SD_INSTRUCT_TECHNICIAN_NAME = "Кривоченко Денис Сергеевич" # ФИО техника в ServiceDesk