@@ -0,0 +1,9 @@
|
||||
# /opt/GigaAM/.env
|
||||
|
||||
|
||||
PW_ID_FTP=FTP
|
||||
PW_ID_TC=bot_tcs
|
||||
PW_ID_SD=sdesktoken
|
||||
PW_ID_AD=AD
|
||||
PW_ID_SQL=boss_base
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,303 @@
|
||||
import os
|
||||
import sys
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Автоматическое определение корневой директории проекта
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Загружаем приватные переменные окружения из вашего .env
|
||||
load_dotenv(os.path.join(BASE_DIR, 'config', '.env'))
|
||||
|
||||
# Карта соответствия: Переменная диспетчера -> Ключ из вашего .env
|
||||
# Объявлена в самом начале, чтобы скрипт знал имена карточек до обращения к API
|
||||
CREDENTIALS_MAP = {
|
||||
"FTP_PASS": os.getenv("PW_ID_FTP", "").strip(' "\'\r\n'), # Мягкий поиск по ключу
|
||||
"API_KEY": os.getenv("PW_ID_SD", "").strip(' "\'\r\n'), # Ищет карточку по значению из .env
|
||||
"AD_PASSWORD": os.getenv("PW_ID_AD", "").strip(' "\'\r\n'), # Ищет карточку по значению из .env
|
||||
}
|
||||
|
||||
# Единственный токен, который может быть зашит в локальном .env, а не в Пассворке
|
||||
EMBEDDING_API_TOKEN = os.getenv("EMBEDDING_API_TOKEN", "").strip(' "\'\r\n')
|
||||
|
||||
# =====================================================================
|
||||
# ИНТЕГРАЦИЯ С 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("LOG: 🔐 Обращение к модулю Passwork и выгрузка сейфа для GigaAM...")
|
||||
|
||||
# Формируем и пробрасываем список обязательных карточек для автозащиты от коллизий
|
||||
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("LOG: 🔐 Распределение секретов и логинов по модулям диспетчера...")
|
||||
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')
|
||||
|
||||
# Динамически вытаскиваем сопутствующие логины из карточек
|
||||
if var_name == "FTP_PASS":
|
||||
globals()["FTP_USER"] = card_data.get("login", "").strip(' "\'\r\n')
|
||||
elif var_name == "AD_PASSWORD":
|
||||
globals()["AD_USER"] = card_data.get("login", "").strip(' "\'\r\n')
|
||||
|
||||
print(f" ✓ {var_name} и логин успешно синхронизированы из карточки '{clean_card_name}'")
|
||||
|
||||
|
||||
# Интеграция с АТС (Выгрузка записей звонков по FTP)
|
||||
FTP_HOST = "10.0.0.7"
|
||||
FTP_DIR = "/zabbix"
|
||||
FTP_ARCHIVE = "/zabbix/archive"
|
||||
|
||||
# =====================================================================
|
||||
# 1. СИСАДМИНСКАЯ ИНФРАСТРУКТУРА, ФЛАСК И ЛОГИРОВАНИЕ
|
||||
# =====================================================================
|
||||
# Порт, на котором Flask-вебхук слушает входящие JSON-пакеты от ManageEngine
|
||||
WEBHOOK_PORT = 5000
|
||||
|
||||
# Путь к файлу сквозного отладочного лога диспетчера
|
||||
WEBHOOK_LOG_FILE = os.path.join(BASE_DIR, 'dispatcher_log.txt')
|
||||
|
||||
# Включение профилирования (замеры времени выполнения этапов обработки заявки)
|
||||
ENABLE_PROFILING = True
|
||||
|
||||
# Ограничение длины текста исторических документов при выводе в файл лога
|
||||
LOG_EXAMPLE_MAX_CHARS = 350
|
||||
|
||||
# Ограничение длины строки текста заявки при выводе в интерактивную CLI-консоль
|
||||
CLI_LOG_MAX_CHARS = 80
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# 2. КОНВЕЙЕР РАСПОЗНАВАНИЯ РЕЧИ И ПЕРВИЧНОЙ ОБРАБОТКИ (ASR PIPELINE)
|
||||
# =====================================================================
|
||||
# Флаг включения суммаризации текста звонка (сейчас отключен для экономии CPU)
|
||||
ENABLE_TEXT_SUMMARIZATION = False
|
||||
|
||||
# Рабочие директории для хранения входящих аудиозаписей и результатов транскрибации
|
||||
AUDIO_DIR = os.path.join(BASE_DIR, 'audio')
|
||||
JSON_DIR = os.path.join(BASE_DIR, 'json')
|
||||
|
||||
# Длина одного чанка (куска аудио) при нарезке для модели распознавания (в секундах)
|
||||
CHUNK_SECONDS = 25
|
||||
|
||||
# Пути к словарям терминов и золотых ИТ-токенов для исправления ошибок транскрипции
|
||||
DICT_PATH = "/opt/dict/dict.json"
|
||||
GOLDEN_DICT_PATH = "/opt/dict/GOLDEN_TERMS.json"
|
||||
|
||||
# Переключатели модулей постобработки и исправления текста после ASR
|
||||
ENABLE_REGEX_CORRECTION = True # Исправление по регулярным выражениям
|
||||
ENABLE_FUZZY_CORRECTION = True # Нечёткое исправление по Левенштейну/словарям
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# 3. ИНТЕГРАЦИЯ С MANAGEENGINE SERVICE DESK API
|
||||
# =====================================================================
|
||||
# Корпоративный URL и API-эндпоинт для работы с заявками по протоколу v3
|
||||
SERVER_URL = "https://servicedesk.sibcem.ru:8080"
|
||||
ENDPOINT = f"{SERVER_URL}/api/v3/requests"
|
||||
|
||||
# Системный email-адрес учетной записи ИИ-сортировщика в Service Desk
|
||||
DEFAULT_REQUESTER = "ai@sibcem.ru"
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# 4. ИНТЕГРАЦИЯ С ACTIVE DIRECTORY (LDAP)
|
||||
# =====================================================================
|
||||
# Контроллер домена и базовая точка поиска пользователей (Base DN)
|
||||
AD_SERVER = "ldap://172.16.20.20"
|
||||
AD_BASE = "OU=-Пользователи,DC=sibcem,DC=ru"
|
||||
|
||||
# Сетевые тайм-ауты (в секундах) для защиты фоновых потоков от зависания на LDAP-запросах
|
||||
AD_CONNECT_TIMEOUT = 5 # Время на установку tcp-соединения
|
||||
AD_RECEIVE_TIMEOUT = 5 # Время ожидания ответа на поисковый запрос
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# 5. ПОЧТОВЫЕ УВЕДОМЛЕНИЯ И АЛЕРТЫ (SMTP)
|
||||
# =====================================================================
|
||||
# Корпоративный почтовый релей и порт (используется стандартный 25 без SSL)
|
||||
SMTP_SERVER = "srvkem-mail.sibcem.ru"
|
||||
SMTP_PORT = 25
|
||||
|
||||
# Отправитель по умолчанию для ИИ-отчетов
|
||||
DEFAULT_EMAIL_FROM = "ai@sibcem.ru"
|
||||
|
||||
# Списки рассылки и исключений для отправки логов принятия решений
|
||||
ALERTS_DISABLED_USERS = ["ds.krivochenko@sibcem.ru"]
|
||||
ALERTS_ALL_TICKETS = ["ds.krivochenko@sibcem.ru"]
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# 6. ВЕКТОРНЫЙ ПОИСК И ЭМБЕДДИНГИ (QDRANT API)
|
||||
# =====================================================================
|
||||
# Адрес, порт и целевая коллекция локального сервера Qdrant
|
||||
QDRANT_HOST = "localhost"
|
||||
QDRANT_PORT = 6333
|
||||
QDRANT_COLLECTION = "tickets"
|
||||
|
||||
# Осредненный лимит выборки документов из Qdrant под дальнейший реранкинг (оптимально для CPU)
|
||||
QDRANT_SEARCH_LIMIT = 20
|
||||
|
||||
# Локальная служба генерации векторов (Embedding API)
|
||||
EMBEDDING_API_URL = "http://127.0.0.1:8010/embed"
|
||||
EMBEDDING_MODEL_NAME = "multilingual-e5-base"
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# 7. ПЕРЕРАНЖИРОВАНИЕ ПРЕЦЕДЕНТОВ (CROSS-ENCODER RERANKER)
|
||||
# =====================================================================
|
||||
# Адрес выделенной службы реранкера (работает на порту 8081)
|
||||
RERANKER_URL = "http://127.0.0.1:8081/rerank"
|
||||
RERANKER_MODEL_NAME = "bge-reranker-v2-m3-Q8_0.gguf"
|
||||
|
||||
# Предохранитель от OOM: максимальное количество символов исторического билета, скармливаемое реранкеру
|
||||
RERANKER_MAX_DOC_CHARS = 1200
|
||||
|
||||
# Жесткий тайм-аут сокета (в секундах) на ожидание пачки документов от реранкера
|
||||
RERANKER_TIMEOUT = 60
|
||||
|
||||
# Коэффициент смешивания скоров (Score Blending):
|
||||
# 1.0 — абсолютная власть реранкера, 0.0 — чистый Qdrant (база векторов)
|
||||
RERANKER_WEIGHT = 0.7
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# 8. ЛОКАЛЬНЫЙ ИНТЕЛЛЕКТ И СЕРВЕРЫ LLM / STT
|
||||
# =====================================================================
|
||||
# Переключатель вызова большой языковой модели
|
||||
ENABLE_OLLAMA = True
|
||||
|
||||
# ГЛОБАЛЬНЫЙ ДИСПЕТЧЕР И АНАЛИЗАТОР: Классификация тикетов (Тяжелый квант Q8)
|
||||
OLLAMA_URL = "http://127.0.0.1:8080/v1/chat/completions"
|
||||
OLLAMA_MODEL = "gemma-4-12b-it-Q8_0"
|
||||
|
||||
# РАСПОЗНАВАНИЕ ЗВОНКОВ: Локальный роутер моделей llama.service (Порт 8080)
|
||||
OLLAMA_SUBJECT_URL = "http://127.0.0.1:8080/v1/chat/completions"
|
||||
OLLAMA_SUBJECT_MODEL = "gemma-4-E4B-it-Q4_K_M"
|
||||
|
||||
# МИКРОСЕРВИС ТРАНСКРИБАЦИИ: Точка подключения к демону GigaAM (Порт 5001)
|
||||
STT_SERVICE_URL = "http://127.0.0.1:5001/transcribe"
|
||||
|
||||
# Размер контекстного окна для слота (динамическое выделение памяти из пула 16384)
|
||||
OLLAMA_NUM_CTX = 12288
|
||||
|
||||
# Параметры инференса текстовой модели
|
||||
OLLAMA_TEMPERATURE = 0.0 # Строгая детерминированность вывода
|
||||
OLLAMA_MAX_TOKENS = 65 # Ограничение длины ответа (модели нужно выдать только имя группы)
|
||||
OLLAMA_TIMEOUT = 1200 # Предельный тайм-аут генерации токенов (в секундах) под CPU-нагрузкой
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# 9. МАТЕМАТИЧЕСКИЕ ФИЛЬТРЫ, ТРИГГЕРЫ МУСОРА И ПОРОГОВЫЕ ОГРАНИЧЕНИЯ
|
||||
# =====================================================================
|
||||
# Осредненный порог относительной уверенности Qdrant. Ниже него — принудительный вызов Qwen 2.5
|
||||
CONFIDENCE_THRESHOLD = 0.85
|
||||
|
||||
# КРИТИЧЕСКИЙ ПРЕДОХРАНИТЕЛЬ: если абсолютный скор лучшего совпадения реранкера ниже этого веса,
|
||||
# сквозной байпас ИИ запрещается, и билет отправляется на перепроверку в Ollama
|
||||
FORCE_OLLAMA_SCORE_THRESHOLD = 0.75
|
||||
|
||||
# Сколько голосов (совпадений) максимум может забрать одна ИТ-группа в векторном пуле
|
||||
QDRANT_MAX_VOTES_PER_GROUP = 10
|
||||
|
||||
# Абсолютный скор, выше которого заявка считается стопроцентным историческим дублем
|
||||
EXACT_MATCH_SCORE_THRESHOLD = 0.9
|
||||
|
||||
# Фильтры детектирования аномального распределения (маркеры мусорных/непонятных заявок)
|
||||
GARBAGE_CONFIDENCE_THRESHOLD = 0.01 # Предельно низкая уверенность
|
||||
GARBAGE_UNIQUE_GROUPS_LIMIT = 4 # Слишком много разных групп в топ-выборке
|
||||
GARBAGE_VARIANCE_THRESHOLD = 0.02 # Слишком плотный шаг весов (нет явного лидера)
|
||||
GARBAGE_MIN_GROUPS_FOR_VARIANCE = 2 # Минимальное число конкурентов для оценки дисперсии
|
||||
GARBAGE_BYPASS_DOMINANCE = 0.90 # Порог доминации, снимающий метку мусора
|
||||
|
||||
# Фильтры условий обхода вызова Ollama (Bypass)
|
||||
OLLAMA_BYPASS_DOMINANCE = 0.95 # Если одна группа заняла 80% топа выборки
|
||||
OLLAMA_BYPASS_MIN_CONFIDENCE = 0.10 # Минимальная базовая уверенность для байпаса
|
||||
OLLAMA_ACCEPTANCE_THRESHOLD = 0.65 # Минимальная уверенность логпробов Ollama для принятия ответа
|
||||
DOMINANCE_TOP_K = 10 # Глубина среза топ-результатов для расчёта коэффициента доминации
|
||||
LOG_TOP_GROUPS_LIMIT = 5 # Количество позиций истории, выводимых в логи структуры decision_log
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# 10. СПРАВОЧНИКИ МАРШРУТИЗАЦИИ, КАТЕГОРИИ И БИЗНЕС-ЛОГИКА АВТОМАТИЗАЦИИ
|
||||
# =====================================================================
|
||||
# White-list валидных ИТ-групп в системе Service Desk Plus
|
||||
VALID_GROUPS = [
|
||||
"CRM", "АХО", "Техподдержка", "1С", "Axapta (Microsoft Dynamics AX)",
|
||||
"АСУТП", "Босс-Кадровик", "ОПС, видеонаблюдение, СКУД, СМТ",
|
||||
"Программисты КТЦ", "Системное администрирование", "Телеком и сообщения",
|
||||
"Битрикс", "СЭД Directum", "Администрирование систем BI", "СБИС", "Служба информационной безопасности", "НСИ"
|
||||
]
|
||||
|
||||
# Группы, для которых открыто прямое автоматическое исполнение Put-запросов назначения через API
|
||||
ALLOWED_ASSIGNMENT_GROUPS = [
|
||||
"Техподдержка КЦ", "Техподдержка ХК", "Техподдержка Тимлюй",
|
||||
"Техподдержка Ангарск", "Техподдержка Искитим", "Техподдержка Топки",
|
||||
"Техподдержка КТЦ", "Техподдержка Волна", "Техподдержка Москва","Телеком и сообщения"
|
||||
]
|
||||
|
||||
# Матрица ответственных менеджеров групп для отправки алертов о сбоях/назначениях билетов
|
||||
GROUP_MANAGERS = {
|
||||
"Техподдержка": ["e.voevodin@sibcem.ru"]
|
||||
}
|
||||
|
||||
# Региональный справочник привязки городов к конкретным Кустовым Центрам (КЦ) и ХК
|
||||
CITY_SUPPORT = {
|
||||
"Ангарск": "Техподдержка Ангарск",
|
||||
"Слюдянка": "Техподдержка Ангарск",
|
||||
"Искитим": "Техподдержка Искитим",
|
||||
"Новосибирск": "Техподдержка КТЦ",
|
||||
"Топки": "Техподдержка Топки",
|
||||
"Кемерово": "Техподдержка ХК",
|
||||
"Москва": "Техподдержка Москва",
|
||||
"Тимлюй": "Техподдержка ХК",
|
||||
"Каменск": "Техподдержка ХК",
|
||||
"Улан-Удэ": "Техподдержка ХК",
|
||||
"Татарский Ключ": "Техподдержка ХК",
|
||||
"Спас-Клепики": "Техподдержка ХК",
|
||||
"Красноярск": "Техподдержка КЦ"
|
||||
}
|
||||
|
||||
# Настройки матрицы автоматического создания уровней согласования руководителями
|
||||
ENABLE_AUTO_APPROVAL = True
|
||||
APPROVAL_CITIES = ["Новосибирск"]
|
||||
APPROVAL_GROUPS = ["1С", "1с", "Программисты КТЦ"]
|
||||
APPROVAL_CATEGORIES = {
|
||||
"ИТ": ["ПО КТЦ", "Проблемы с Договорной Работой"],
|
||||
"1С": ["*"],
|
||||
"1с": ["*"]
|
||||
}
|
||||
|
||||
# План «Б» маршрутизации: жесткое определение локации по телефонному префиксу внутренней АТС
|
||||
PREFIX_ROUTING = {
|
||||
"700": {"city": "Красноярск", "company": "ООО Комбинат Волна"},
|
||||
"702": {"city": "Кемерово"},
|
||||
"703": {"city": "Новосибирск"},
|
||||
"704": {"city": "Красноярск"},
|
||||
"705": {"city": "Каменск"},
|
||||
"701": {"city": "Ангарск"},
|
||||
"706": {"city": "Ангарск"},
|
||||
"707": {"city": "Ангарск"},
|
||||
"709": {"city": "Москва"},
|
||||
"724": {"city": "Искитим"},
|
||||
"71": {"city": "Топки"}
|
||||
}
|
||||
Reference in New Issue
Block a user