222 lines
13 KiB
Python
222 lines
13 KiB
Python
# /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 = False # Модуль создания заявок в техподдержку
|
|
ENABLE_PHOTO_BOT = False # Модуль обработки фото/сканов
|
|
ENABLE_TRANSCRIPTION = True # Модуль расшифровки голосовых сообщений (Whisper)
|
|
ENABLE_SEARCH_BOT = False # Модуль интеллектуального поиска по регламентам (RAG)
|
|
ENABLE_INSTRUCT = False # Модуль инструкций (Trueconf, Почта)
|
|
ENABLE_LK = True # Личный кабинет сотрудника (отпуска, расчетные листки, справки)
|
|
|
|
# =========================================================
|
|
# 2. КОНТРОЛЬ ДОСТУПА
|
|
# =========================================================
|
|
ENABLE_WHITELIST = False # Включить режим закрытого бета-тестирования
|
|
ALLOWED_USERS = [ # Список TrueConf ID разрешенных пользователей
|
|
|
|
]
|
|
|
|
# =========================================================
|
|
# 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 = "54966d1f56c2fda8e263a70c3a65ff0fad27ef7d"
|
|
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
|